LCOV - code coverage report
Current view: top level - drivers/net/mlx5 - mlx5_flow.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 3468 0.0 %
Date: 2025-05-01 17:49:45 Functions: 0 241 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 2549 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2016 6WIND S.A.
       3                 :            :  * Copyright 2016 Mellanox Technologies, Ltd
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <stdalign.h>
       7                 :            : #include <stdint.h>
       8                 :            : #include <string.h>
       9                 :            : #include <stdbool.h>
      10                 :            : #include <sys/queue.h>
      11                 :            : 
      12                 :            : #include <eal_export.h>
      13                 :            : #include <rte_common.h>
      14                 :            : #include <rte_ether.h>
      15                 :            : #include <ethdev_driver.h>
      16                 :            : #include <rte_eal_paging.h>
      17                 :            : #include <rte_flow.h>
      18                 :            : #include <rte_cycles.h>
      19                 :            : #include <rte_flow_driver.h>
      20                 :            : #include <rte_malloc.h>
      21                 :            : #include <rte_ip.h>
      22                 :            : 
      23                 :            : #include <mlx5_glue.h>
      24                 :            : #include <mlx5_devx_cmds.h>
      25                 :            : #include <mlx5_prm.h>
      26                 :            : #include <mlx5_malloc.h>
      27                 :            : 
      28                 :            : #include "mlx5_defs.h"
      29                 :            : #include "mlx5.h"
      30                 :            : #include "mlx5_flow.h"
      31                 :            : #include "mlx5_flow_os.h"
      32                 :            : #include "mlx5_rx.h"
      33                 :            : #include "mlx5_tx.h"
      34                 :            : #include "mlx5_common_os.h"
      35                 :            : #include "rte_pmd_mlx5.h"
      36                 :            : 
      37                 :            : /*
      38                 :            :  * Shared array for quick translation between port_id and vport mask/values
      39                 :            :  * used for HWS rules.
      40                 :            :  */
      41                 :            : struct flow_hw_port_info mlx5_flow_hw_port_infos[RTE_MAX_ETHPORTS];
      42                 :            : 
      43                 :            : struct tunnel_default_miss_ctx {
      44                 :            :         uint16_t *queue;
      45                 :            :         __extension__
      46                 :            :         union {
      47                 :            :                 struct rte_flow_action_rss action_rss;
      48                 :            :                 struct rte_flow_action_queue miss_queue;
      49                 :            :                 struct rte_flow_action_jump miss_jump;
      50                 :            :                 uint8_t raw[0];
      51                 :            :         };
      52                 :            : };
      53                 :            : 
      54                 :            : void
      55                 :          0 : mlx5_indirect_list_handles_release(struct rte_eth_dev *dev)
      56                 :            : {
      57                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
      58                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
      59                 :            :         struct rte_flow_error error;
      60                 :            : #endif
      61                 :            : 
      62         [ #  # ]:          0 :         while (!LIST_EMPTY(&priv->indirect_list_head)) {
      63                 :            :                 struct mlx5_indirect_list *e =
      64                 :            :                         LIST_FIRST(&priv->indirect_list_head);
      65                 :            : 
      66         [ #  # ]:          0 :                 LIST_REMOVE(e, entry);
      67   [ #  #  #  # ]:          0 :                 switch (e->type) {
      68                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
      69                 :          0 :                 case MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR:
      70                 :          0 :                         mlx5_hw_mirror_destroy(dev, (struct mlx5_mirror *)e);
      71                 :          0 :                 break;
      72                 :          0 :                 case MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY:
      73                 :          0 :                         mlx5_destroy_legacy_indirect(dev, e);
      74                 :          0 :                         break;
      75                 :          0 :                 case MLX5_INDIRECT_ACTION_LIST_TYPE_REFORMAT:
      76                 :          0 :                         mlx5_reformat_action_destroy(dev,
      77                 :            :                                 (struct rte_flow_action_list_handle *)e, &error);
      78                 :          0 :                         break;
      79                 :            : #endif
      80                 :          0 :                 default:
      81                 :          0 :                         DRV_LOG(ERR, "invalid indirect list type");
      82                 :            :                         MLX5_ASSERT(false);
      83                 :          0 :                         break;
      84                 :            :                 }
      85                 :            :         }
      86                 :          0 : }
      87                 :            : 
      88                 :            : static int
      89                 :            : flow_tunnel_add_default_miss(struct rte_eth_dev *dev,
      90                 :            :                              struct rte_flow *flow,
      91                 :            :                              const struct rte_flow_attr *attr,
      92                 :            :                              const struct rte_flow_action *app_actions,
      93                 :            :                              uint32_t flow_idx,
      94                 :            :                              const struct mlx5_flow_tunnel *tunnel,
      95                 :            :                              struct tunnel_default_miss_ctx *ctx,
      96                 :            :                              struct rte_flow_error *error);
      97                 :            : static struct mlx5_flow_tunnel *
      98                 :            : mlx5_find_tunnel_id(struct rte_eth_dev *dev, uint32_t id);
      99                 :            : static void
     100                 :            : mlx5_flow_tunnel_free(struct rte_eth_dev *dev, struct mlx5_flow_tunnel *tunnel);
     101                 :            : static uint32_t
     102                 :            : tunnel_flow_group_to_flow_table(struct rte_eth_dev *dev,
     103                 :            :                                 const struct mlx5_flow_tunnel *tunnel,
     104                 :            :                                 uint32_t group, uint32_t *table,
     105                 :            :                                 struct rte_flow_error *error);
     106                 :            : 
     107                 :            : /** Device flow drivers. */
     108                 :            : extern const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops;
     109                 :            : 
     110                 :            : const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops;
     111                 :            : 
     112                 :            : const struct mlx5_flow_driver_ops *flow_drv_ops[] = {
     113                 :            :         [MLX5_FLOW_TYPE_MIN] = &mlx5_flow_null_drv_ops,
     114                 :            : #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
     115                 :            :         [MLX5_FLOW_TYPE_DV] = &mlx5_flow_dv_drv_ops,
     116                 :            : #endif
     117                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
     118                 :            :         [MLX5_FLOW_TYPE_HW] = &mlx5_flow_hw_drv_ops,
     119                 :            : #endif
     120                 :            :         [MLX5_FLOW_TYPE_VERBS] = &mlx5_flow_verbs_drv_ops,
     121                 :            :         [MLX5_FLOW_TYPE_MAX] = &mlx5_flow_null_drv_ops
     122                 :            : };
     123                 :            : 
     124                 :            : /** Helper macro to build input graph for mlx5_flow_expand_rss(). */
     125                 :            : #define MLX5_FLOW_EXPAND_RSS_NEXT(...) \
     126                 :            :         (const int []){ \
     127                 :            :                 __VA_ARGS__, 0, \
     128                 :            :         }
     129                 :            : 
     130                 :            : /** Node object of input graph for mlx5_flow_expand_rss(). */
     131                 :            : struct mlx5_flow_expand_node {
     132                 :            :         const int *const next;
     133                 :            :         /**<
     134                 :            :          * List of next node indexes. Index 0 is interpreted as a terminator.
     135                 :            :          */
     136                 :            :         const enum rte_flow_item_type type;
     137                 :            :         /**< Pattern item type of current node. */
     138                 :            :         uint64_t rss_types;
     139                 :            :         /**<
     140                 :            :          * RSS types bit-field associated with this node
     141                 :            :          * (see RTE_ETH_RSS_* definitions).
     142                 :            :          */
     143                 :            :         uint64_t node_flags;
     144                 :            :         /**<
     145                 :            :          *  Bit-fields that define how the node is used in the expansion.
     146                 :            :          * (see MLX5_EXPANSION_NODE_* definitions).
     147                 :            :          */
     148                 :            : };
     149                 :            : 
     150                 :            : /** Keep same format with mlx5_flow_expand_rss to share the buffer for expansion. */
     151                 :            : struct mlx5_flow_expand_sqn {
     152                 :            :         uint32_t entries; /** Number of entries */
     153                 :            :         struct {
     154                 :            :                 struct rte_flow_item *pattern; /**< Expanded pattern array. */
     155                 :            :                 uint32_t priority; /**< Priority offset for each expansion. */
     156                 :            :         } entry[];
     157                 :            : };
     158                 :            : 
     159                 :            : /* Optional expand field. The expansion alg will not go deeper. */
     160                 :            : #define MLX5_EXPANSION_NODE_OPTIONAL (UINT64_C(1) << 0)
     161                 :            : 
     162                 :            : /* The node is not added implicitly as expansion to the flow pattern.
     163                 :            :  * If the node type does not match the flow pattern item type, the
     164                 :            :  * expansion alg will go deeper to its next items.
     165                 :            :  * In the current implementation, the list of next nodes indexes can
     166                 :            :  * have up to one node with this flag set and it has to be the last
     167                 :            :  * node index (before the list terminator).
     168                 :            :  */
     169                 :            : #define MLX5_EXPANSION_NODE_EXPLICIT (UINT64_C(1) << 1)
     170                 :            : 
     171                 :            : /** Object returned by mlx5_flow_expand_rss(). */
     172                 :            : struct mlx5_flow_expand_rss {
     173                 :            :         uint32_t entries;
     174                 :            :         /**< Number of entries @p patterns and @p priorities. */
     175                 :            :         struct {
     176                 :            :                 struct rte_flow_item *pattern; /**< Expanded pattern array. */
     177                 :            :                 uint32_t priority; /**< Priority offset for each expansion. */
     178                 :            :         } entry[];
     179                 :            : };
     180                 :            : 
     181                 :            : static void
     182                 :            : mlx5_dbg__print_pattern(const struct rte_flow_item *item);
     183                 :            : 
     184                 :            : static const struct mlx5_flow_expand_node *
     185                 :            : mlx5_flow_expand_rss_adjust_node(const struct rte_flow_item *pattern,
     186                 :            :                 unsigned int item_idx,
     187                 :            :                 const struct mlx5_flow_expand_node graph[],
     188                 :            :                 const struct mlx5_flow_expand_node *node);
     189                 :            : 
     190                 :            : static __rte_always_inline int
     191                 :            : mlx5_need_cache_flow(const struct mlx5_priv *priv,
     192                 :            :                      const struct rte_flow_attr *attr)
     193                 :            : {
     194   [ #  #  #  #  :          0 :         return priv->isolated && priv->sh->config.dv_flow_en == 1 &&
             #  #  #  # ]
     195   [ #  #  #  # ]:          0 :                 (attr ? !attr->group : true) &&
     196   [ #  #  #  #  :          0 :                 priv->mode_info.mode == RTE_PMD_MLX5_FLOW_ENGINE_MODE_STANDBY &&
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     197   [ #  #  #  #  :          0 :                 (!priv->sh->config.dv_esw_en || !priv->sh->config.fdb_def_rule);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     198                 :            : }
     199                 :            : 
     200                 :            : static bool
     201                 :          0 : mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
     202                 :            : {
     203         [ #  # ]:          0 :         switch (item->type) {
     204                 :            :         case RTE_FLOW_ITEM_TYPE_ETH:
     205                 :            :         case RTE_FLOW_ITEM_TYPE_VLAN:
     206                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:
     207                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:
     208                 :            :         case RTE_FLOW_ITEM_TYPE_UDP:
     209                 :            :         case RTE_FLOW_ITEM_TYPE_TCP:
     210                 :            :         case RTE_FLOW_ITEM_TYPE_ESP:
     211                 :            :         case RTE_FLOW_ITEM_TYPE_ICMP:
     212                 :            :         case RTE_FLOW_ITEM_TYPE_ICMP6:
     213                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN:
     214                 :            :         case RTE_FLOW_ITEM_TYPE_NVGRE:
     215                 :            :         case RTE_FLOW_ITEM_TYPE_GRE:
     216                 :            :         case RTE_FLOW_ITEM_TYPE_GENEVE:
     217                 :            :         case RTE_FLOW_ITEM_TYPE_MPLS:
     218                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
     219                 :            :         case RTE_FLOW_ITEM_TYPE_GRE_KEY:
     220                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
     221                 :            :         case RTE_FLOW_ITEM_TYPE_GTP:
     222                 :            :                 return true;
     223                 :            :         default:
     224                 :            :                 break;
     225                 :            :         }
     226                 :          0 :         return false;
     227                 :            : }
     228                 :            : 
     229                 :            : /**
     230                 :            :  * Network Service Header (NSH) and its next protocol values
     231                 :            :  * are described in RFC-8393.
     232                 :            :  */
     233                 :            : static enum rte_flow_item_type
     234                 :            : mlx5_nsh_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask)
     235                 :            : {
     236                 :            :         enum rte_flow_item_type type;
     237                 :            : 
     238                 :          0 :         switch (proto_mask & proto_spec) {
     239                 :            :         case 0:
     240                 :            :                 type = RTE_FLOW_ITEM_TYPE_VOID;
     241                 :            :                 break;
     242                 :            :         case RTE_VXLAN_GPE_TYPE_IPV4:
     243                 :            :                 type = RTE_FLOW_ITEM_TYPE_IPV4;
     244                 :            :                 break;
     245                 :            :         case RTE_VXLAN_GPE_TYPE_IPV6:
     246                 :            :                 type = RTE_VXLAN_GPE_TYPE_IPV6;
     247                 :            :                 break;
     248                 :            :         case RTE_VXLAN_GPE_TYPE_ETH:
     249                 :            :                 type = RTE_FLOW_ITEM_TYPE_ETH;
     250                 :            :                 break;
     251                 :            :         default:
     252                 :            :                 type = RTE_FLOW_ITEM_TYPE_END;
     253                 :            :         }
     254                 :            :         return type;
     255                 :            : }
     256                 :            : 
     257                 :            : static enum rte_flow_item_type
     258                 :            : mlx5_inet_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask)
     259                 :            : {
     260                 :            :         enum rte_flow_item_type type;
     261                 :            : 
     262   [ #  #  #  #  :          0 :         switch (proto_mask & proto_spec) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     263                 :            :         case 0:
     264                 :            :                 type = RTE_FLOW_ITEM_TYPE_VOID;
     265                 :            :                 break;
     266                 :          0 :         case IPPROTO_UDP:
     267                 :            :                 type = RTE_FLOW_ITEM_TYPE_UDP;
     268                 :          0 :                 break;
     269                 :          0 :         case IPPROTO_TCP:
     270                 :            :                 type = RTE_FLOW_ITEM_TYPE_TCP;
     271                 :          0 :                 break;
     272                 :          0 :         case IPPROTO_IPIP:
     273                 :            :                 type = RTE_FLOW_ITEM_TYPE_IPV4;
     274                 :          0 :                 break;
     275                 :          0 :         case IPPROTO_IPV6:
     276                 :            :                 type = RTE_FLOW_ITEM_TYPE_IPV6;
     277                 :          0 :                 break;
     278                 :          0 :         case IPPROTO_ESP:
     279                 :            :                 type = RTE_FLOW_ITEM_TYPE_ESP;
     280                 :          0 :                 break;
     281                 :          0 :         default:
     282                 :            :                 type = RTE_FLOW_ITEM_TYPE_END;
     283                 :            :         }
     284                 :            :         return type;
     285                 :            : }
     286                 :            : 
     287                 :            : static enum rte_flow_item_type
     288                 :            : mlx5_ethertype_to_item_type(rte_be16_t type_spec,
     289                 :            :                             rte_be16_t type_mask, bool is_tunnel)
     290                 :            : {
     291                 :            :         enum rte_flow_item_type type;
     292                 :            : 
     293   [ #  #  #  #  :          0 :         switch (rte_be_to_cpu_16(type_spec & type_mask)) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     294                 :            :         case 0:
     295                 :            :                 type = RTE_FLOW_ITEM_TYPE_VOID;
     296                 :            :                 break;
     297                 :          0 :         case RTE_ETHER_TYPE_TEB:
     298                 :            :                 type = is_tunnel ?
     299                 :            :                        RTE_FLOW_ITEM_TYPE_ETH : RTE_FLOW_ITEM_TYPE_END;
     300                 :            :                 break;
     301                 :          0 :         case RTE_ETHER_TYPE_VLAN:
     302                 :            :                 type = !is_tunnel ?
     303                 :            :                        RTE_FLOW_ITEM_TYPE_VLAN : RTE_FLOW_ITEM_TYPE_END;
     304                 :            :                 break;
     305                 :          0 :         case RTE_ETHER_TYPE_IPV4:
     306                 :            :                 type = RTE_FLOW_ITEM_TYPE_IPV4;
     307                 :          0 :                 break;
     308                 :          0 :         case RTE_ETHER_TYPE_IPV6:
     309                 :            :                 type = RTE_FLOW_ITEM_TYPE_IPV6;
     310                 :          0 :                 break;
     311                 :          0 :         default:
     312                 :            :                 type = RTE_FLOW_ITEM_TYPE_END;
     313                 :            :         }
     314                 :            :         return type;
     315                 :            : }
     316                 :            : 
     317                 :            : static enum rte_flow_item_type
     318                 :          0 : mlx5_flow_expand_rss_item_complete(const struct rte_flow_item *item)
     319                 :            : {
     320                 :            : #define MLX5_XSET_ITEM_MASK_SPEC(type, fld)                              \
     321                 :            :         do {                                                             \
     322                 :            :                 const void *m = item->mask;                              \
     323                 :            :                 const void *s = item->spec;                              \
     324                 :            :                 mask = m ?                                               \
     325                 :            :                         ((const struct rte_flow_item_##type *)m)->fld :  \
     326                 :            :                         rte_flow_item_##type##_mask.fld;                 \
     327                 :            :                 spec = ((const struct rte_flow_item_##type *)s)->fld;    \
     328                 :            :         } while (0)
     329                 :            : 
     330                 :            :         enum rte_flow_item_type ret;
     331                 :            :         uint16_t spec, mask;
     332                 :            : 
     333   [ #  #  #  # ]:          0 :         if (item == NULL || item->spec == NULL)
     334                 :            :                 return RTE_FLOW_ITEM_TYPE_VOID;
     335   [ #  #  #  #  :          0 :         switch (item->type) {
             #  #  #  # ]
     336                 :          0 :         case RTE_FLOW_ITEM_TYPE_ETH:
     337         [ #  # ]:          0 :                 MLX5_XSET_ITEM_MASK_SPEC(eth, hdr.ether_type);
     338         [ #  # ]:          0 :                 if (!mask)
     339                 :            :                         return RTE_FLOW_ITEM_TYPE_VOID;
     340                 :            :                 ret = mlx5_ethertype_to_item_type(spec, mask, false);
     341                 :            :                 break;
     342                 :          0 :         case RTE_FLOW_ITEM_TYPE_VLAN:
     343         [ #  # ]:          0 :                 MLX5_XSET_ITEM_MASK_SPEC(vlan, hdr.eth_proto);
     344         [ #  # ]:          0 :                 if (!mask)
     345                 :            :                         return RTE_FLOW_ITEM_TYPE_VOID;
     346                 :            :                 ret = mlx5_ethertype_to_item_type(spec, mask, false);
     347                 :            :                 break;
     348                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV4:
     349         [ #  # ]:          0 :                 MLX5_XSET_ITEM_MASK_SPEC(ipv4, hdr.next_proto_id);
     350         [ #  # ]:          0 :                 if (!mask)
     351                 :            :                         return RTE_FLOW_ITEM_TYPE_VOID;
     352                 :            :                 ret = mlx5_inet_proto_to_item_type(spec, mask);
     353                 :            :                 break;
     354                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV6:
     355         [ #  # ]:          0 :                 MLX5_XSET_ITEM_MASK_SPEC(ipv6, hdr.proto);
     356         [ #  # ]:          0 :                 if (!mask)
     357                 :            :                         return RTE_FLOW_ITEM_TYPE_VOID;
     358                 :            :                 ret = mlx5_inet_proto_to_item_type(spec, mask);
     359                 :            :                 break;
     360                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE:
     361   [ #  #  #  # ]:          0 :                 MLX5_XSET_ITEM_MASK_SPEC(geneve, protocol);
     362                 :            :                 ret = mlx5_ethertype_to_item_type(spec, mask, true);
     363                 :            :                 break;
     364                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE:
     365   [ #  #  #  # ]:          0 :                 MLX5_XSET_ITEM_MASK_SPEC(gre, protocol);
     366                 :            :                 ret = mlx5_ethertype_to_item_type(spec, mask, true);
     367                 :            :                 break;
     368                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
     369         [ #  # ]:          0 :                 MLX5_XSET_ITEM_MASK_SPEC(vxlan_gpe, hdr.proto);
     370         [ #  # ]:          0 :                 ret = mlx5_nsh_proto_to_item_type(spec, mask);
     371                 :            :                 break;
     372                 :            :         default:
     373                 :            :                 ret = RTE_FLOW_ITEM_TYPE_VOID;
     374                 :            :                 break;
     375                 :            :         }
     376                 :            :         return ret;
     377                 :            : #undef MLX5_XSET_ITEM_MASK_SPEC
     378                 :            : }
     379                 :            : 
     380                 :            : static const int *
     381                 :            : mlx5_flow_expand_rss_skip_explicit(const struct mlx5_flow_expand_node graph[],
     382                 :            :                 const int *next_node)
     383                 :            : {
     384                 :            :         const struct mlx5_flow_expand_node *node = NULL;
     385                 :            :         const int *next = next_node;
     386                 :            : 
     387   [ #  #  #  #  :          0 :         while (next && *next) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     388                 :            :                 /*
     389                 :            :                  * Skip the nodes with the MLX5_EXPANSION_NODE_EXPLICIT
     390                 :            :                  * flag set, because they were not found in the flow pattern.
     391                 :            :                  */
     392                 :          0 :                 node = &graph[*next];
     393   [ #  #  #  #  :          0 :                 if (!(node->node_flags & MLX5_EXPANSION_NODE_EXPLICIT))
             #  #  #  # ]
     394                 :            :                         break;
     395                 :          0 :                 next = node->next;
     396                 :            :         }
     397                 :            :         return next;
     398                 :            : }
     399                 :            : 
     400                 :            : #define MLX5_RSS_EXP_ELT_N 32
     401                 :            : 
     402                 :            : /**
     403                 :            :  * Expand RSS flows into several possible flows according to the RSS hash
     404                 :            :  * fields requested and the driver capabilities.
     405                 :            :  *
     406                 :            :  * @param[out] buf
     407                 :            :  *   Buffer to store the result expansion.
     408                 :            :  * @param[in] size
     409                 :            :  *   Buffer size in bytes. If 0, @p buf can be NULL.
     410                 :            :  * @param[in] pattern
     411                 :            :  *   User flow pattern.
     412                 :            :  * @param[in] types
     413                 :            :  *   RSS types to expand (see RTE_ETH_RSS_* definitions).
     414                 :            :  * @param[in] graph
     415                 :            :  *   Input graph to expand @p pattern according to @p types.
     416                 :            :  * @param[in] graph_root_index
     417                 :            :  *   Index of root node in @p graph, typically 0.
     418                 :            :  *
     419                 :            :  * @return
     420                 :            :  *   A positive value representing the size of @p buf in bytes regardless of
     421                 :            :  *   @p size on success, a negative errno value otherwise and rte_errno is
     422                 :            :  *   set, the following errors are defined:
     423                 :            :  *
     424                 :            :  *   -E2BIG: graph-depth @p graph is too deep.
     425                 :            :  *   -EINVAL: @p size has not enough space for expanded pattern.
     426                 :            :  */
     427                 :            : static int
     428                 :          0 : mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
     429                 :            :                      const struct rte_flow_item *pattern, uint64_t types,
     430                 :            :                      const struct mlx5_flow_expand_node graph[],
     431                 :            :                      int graph_root_index)
     432                 :            : {
     433                 :            :         const struct rte_flow_item *item;
     434         [ #  # ]:          0 :         const struct mlx5_flow_expand_node *node = &graph[graph_root_index];
     435                 :            :         const int *next_node;
     436                 :            :         const int *stack[MLX5_RSS_EXP_ELT_N];
     437                 :            :         int stack_pos = 0;
     438                 :            :         struct rte_flow_item flow_items[MLX5_RSS_EXP_ELT_N];
     439                 :            :         unsigned int i, item_idx, last_expand_item_idx = 0;
     440                 :            :         size_t lsize;
     441                 :            :         size_t user_pattern_size = 0;
     442                 :            :         void *addr = NULL;
     443                 :            :         const struct mlx5_flow_expand_node *next = NULL;
     444                 :            :         struct rte_flow_item missed_item;
     445                 :            :         int missed = 0;
     446                 :            :         int elt = 0;
     447                 :            :         const struct rte_flow_item *last_expand_item = NULL;
     448                 :            : 
     449                 :            :         memset(&missed_item, 0, sizeof(missed_item));
     450                 :            :         lsize = offsetof(struct mlx5_flow_expand_rss, entry) +
     451                 :            :                 MLX5_RSS_EXP_ELT_N * sizeof(buf->entry[0]);
     452         [ #  # ]:          0 :         if (lsize > size)
     453                 :            :                 return -EINVAL;
     454                 :          0 :         buf->entry[0].priority = 0;
     455                 :          0 :         buf->entry[0].pattern = (void *)&buf->entry[MLX5_RSS_EXP_ELT_N];
     456                 :          0 :         buf->entries = 0;
     457                 :            :         addr = buf->entry[0].pattern;
     458                 :          0 :         for (item = pattern, item_idx = 0;
     459         [ #  # ]:          0 :                         item->type != RTE_FLOW_ITEM_TYPE_END;
     460                 :          0 :                         item++, item_idx++) {
     461         [ #  # ]:          0 :                 if (!mlx5_flow_is_rss_expandable_item(item)) {
     462                 :          0 :                         user_pattern_size += sizeof(*item);
     463                 :          0 :                         continue;
     464                 :            :                 }
     465                 :            :                 last_expand_item = item;
     466                 :            :                 last_expand_item_idx = item_idx;
     467                 :            :                 i = 0;
     468   [ #  #  #  # ]:          0 :                 while (node->next && node->next[i]) {
     469                 :          0 :                         next = &graph[node->next[i]];
     470         [ #  # ]:          0 :                         if (next->type == item->type)
     471                 :            :                                 break;
     472         [ #  # ]:          0 :                         if (next->node_flags & MLX5_EXPANSION_NODE_EXPLICIT) {
     473                 :            :                                 node = next;
     474                 :            :                                 i = 0;
     475                 :            :                         } else {
     476                 :          0 :                                 ++i;
     477                 :            :                         }
     478                 :            :                 }
     479         [ #  # ]:          0 :                 if (next)
     480                 :            :                         node = next;
     481                 :          0 :                 user_pattern_size += sizeof(*item);
     482                 :            :         }
     483                 :          0 :         user_pattern_size += sizeof(*item); /* Handle END item. */
     484                 :          0 :         lsize += user_pattern_size;
     485         [ #  # ]:          0 :         if (lsize > size)
     486                 :            :                 return -EINVAL;
     487                 :            :         /* Copy the user pattern in the first entry of the buffer. */
     488                 :            :         rte_memcpy(addr, pattern, user_pattern_size);
     489                 :          0 :         addr = (void *)(((uintptr_t)addr) + user_pattern_size);
     490                 :          0 :         buf->entries = 1;
     491                 :            :         /* Start expanding. */
     492                 :            :         memset(flow_items, 0, sizeof(flow_items));
     493                 :            :         user_pattern_size -= sizeof(*item);
     494                 :            :         /*
     495                 :            :          * Check if the last valid item has spec set, need complete pattern,
     496                 :            :          * and the pattern can be used for expansion.
     497                 :            :          */
     498                 :          0 :         missed_item.type = mlx5_flow_expand_rss_item_complete(last_expand_item);
     499         [ #  # ]:          0 :         if (missed_item.type == RTE_FLOW_ITEM_TYPE_END) {
     500                 :            :                 /* Item type END indicates expansion is not required. */
     501                 :          0 :                 return lsize;
     502                 :            :         }
     503         [ #  # ]:          0 :         if (missed_item.type != RTE_FLOW_ITEM_TYPE_VOID) {
     504                 :            :                 next = NULL;
     505                 :            :                 missed = 1;
     506                 :            :                 i = 0;
     507   [ #  #  #  # ]:          0 :                 while (node->next && node->next[i]) {
     508                 :          0 :                         next = &graph[node->next[i]];
     509         [ #  # ]:          0 :                         if (next->type == missed_item.type) {
     510                 :          0 :                                 flow_items[0].type = missed_item.type;
     511                 :            :                                 flow_items[1].type = RTE_FLOW_ITEM_TYPE_END;
     512                 :          0 :                                 break;
     513                 :            :                         }
     514         [ #  # ]:          0 :                         if (next->node_flags & MLX5_EXPANSION_NODE_EXPLICIT) {
     515                 :            :                                 node = next;
     516                 :            :                                 i = 0;
     517                 :            :                         } else {
     518                 :          0 :                                 ++i;
     519                 :            :                         }
     520                 :            :                         next = NULL;
     521                 :            :                 }
     522                 :            :         }
     523         [ #  # ]:          0 :         if (next && missed) {
     524                 :            :                 elt = 2; /* missed item + item end. */
     525                 :            :                 node = next;
     526                 :          0 :                 lsize += elt * sizeof(*item) + user_pattern_size;
     527         [ #  # ]:          0 :                 if (lsize > size)
     528                 :            :                         return -EINVAL;
     529         [ #  # ]:          0 :                 if (node->rss_types & types) {
     530                 :          0 :                         buf->entry[buf->entries].priority = 1;
     531                 :          0 :                         buf->entry[buf->entries].pattern = addr;
     532                 :          0 :                         buf->entries++;
     533         [ #  # ]:          0 :                         rte_memcpy(addr, buf->entry[0].pattern,
     534                 :            :                                    user_pattern_size);
     535         [ #  # ]:          0 :                         addr = (void *)(((uintptr_t)addr) + user_pattern_size);
     536                 :            :                         rte_memcpy(addr, flow_items, elt * sizeof(*item));
     537                 :          0 :                         addr = (void *)(((uintptr_t)addr) +
     538                 :            :                                         elt * sizeof(*item));
     539                 :            :                 }
     540         [ #  # ]:          0 :         } else if (last_expand_item != NULL) {
     541                 :          0 :                 node = mlx5_flow_expand_rss_adjust_node(pattern,
     542                 :            :                                 last_expand_item_idx, graph, node);
     543                 :            :         }
     544                 :            :         memset(flow_items, 0, sizeof(flow_items));
     545                 :            :         next_node = mlx5_flow_expand_rss_skip_explicit(graph,
     546                 :          0 :                         node->next);
     547                 :          0 :         stack[stack_pos] = next_node;
     548         [ #  # ]:          0 :         node = next_node ? &graph[*next_node] : NULL;
     549         [ #  # ]:          0 :         while (node) {
     550                 :          0 :                 flow_items[stack_pos].type = node->type;
     551         [ #  # ]:          0 :                 if (node->rss_types & types) {
     552                 :            :                         size_t n;
     553                 :            :                         /*
     554                 :            :                          * compute the number of items to copy from the
     555                 :            :                          * expansion and copy it.
     556                 :            :                          * When the stack_pos is 0, there are 1 element in it,
     557                 :            :                          * plus the addition END item.
     558                 :            :                          */
     559                 :          0 :                         elt = stack_pos + 2;
     560                 :          0 :                         flow_items[stack_pos + 1].type = RTE_FLOW_ITEM_TYPE_END;
     561                 :          0 :                         lsize += elt * sizeof(*item) + user_pattern_size;
     562         [ #  # ]:          0 :                         if (lsize > size)
     563                 :            :                                 return -EINVAL;
     564                 :            :                         n = elt * sizeof(*item);
     565                 :            :                         MLX5_ASSERT((buf->entries) < MLX5_RSS_EXP_ELT_N);
     566                 :          0 :                         buf->entry[buf->entries].priority =
     567                 :          0 :                                 stack_pos + 1 + missed;
     568                 :          0 :                         buf->entry[buf->entries].pattern = addr;
     569                 :          0 :                         buf->entries++;
     570         [ #  # ]:          0 :                         rte_memcpy(addr, buf->entry[0].pattern,
     571                 :            :                                    user_pattern_size);
     572                 :          0 :                         addr = (void *)(((uintptr_t)addr) +
     573                 :            :                                         user_pattern_size);
     574         [ #  # ]:          0 :                         rte_memcpy(addr, &missed_item,
     575                 :            :                                    missed * sizeof(*item));
     576         [ #  # ]:          0 :                         addr = (void *)(((uintptr_t)addr) +
     577                 :            :                                 missed * sizeof(*item));
     578                 :            :                         rte_memcpy(addr, flow_items, n);
     579                 :          0 :                         addr = (void *)(((uintptr_t)addr) + n);
     580                 :            :                 }
     581                 :            :                 /* Go deeper. */
     582         [ #  # ]:          0 :                 if (!(node->node_flags & MLX5_EXPANSION_NODE_OPTIONAL) &&
     583         [ #  # ]:          0 :                                 node->next) {
     584                 :            :                         next_node = mlx5_flow_expand_rss_skip_explicit(graph,
     585                 :            :                                         node->next);
     586         [ #  # ]:          0 :                         if (stack_pos++ == MLX5_RSS_EXP_ELT_N) {
     587                 :          0 :                                 rte_errno = E2BIG;
     588                 :          0 :                                 return -rte_errno;
     589                 :            :                         }
     590                 :          0 :                         stack[stack_pos] = next_node;
     591         [ #  # ]:          0 :                 } else if (*(next_node + 1)) {
     592                 :            :                         /* Follow up with the next possibility. */
     593                 :          0 :                         next_node = mlx5_flow_expand_rss_skip_explicit(graph,
     594                 :            :                                         ++next_node);
     595         [ #  # ]:          0 :                 } else if (!stack_pos) {
     596                 :            :                         /*
     597                 :            :                          * Completing the traverse over the different paths.
     598                 :            :                          * The next_node is advanced to the terminator.
     599                 :            :                          */
     600                 :          0 :                         ++next_node;
     601                 :            :                 } else {
     602                 :            :                         /* Move to the next path. */
     603         [ #  # ]:          0 :                         while (stack_pos) {
     604                 :          0 :                                 next_node = stack[--stack_pos];
     605                 :          0 :                                 next_node++;
     606         [ #  # ]:          0 :                                 if (*next_node)
     607                 :            :                                         break;
     608                 :            :                         }
     609                 :            :                         next_node = mlx5_flow_expand_rss_skip_explicit(graph,
     610                 :            :                                         next_node);
     611                 :          0 :                         stack[stack_pos] = next_node;
     612                 :            :                 }
     613   [ #  #  #  # ]:          0 :                 node = next_node && *next_node ? &graph[*next_node] : NULL;
     614                 :            :         };
     615                 :          0 :         return lsize;
     616                 :            : }
     617                 :            : 
     618                 :            : /**
     619                 :            :  * Expand SQN flows into several possible flows according to the Tx queue
     620                 :            :  * number
     621                 :            :  *
     622                 :            :  * @param[in] buf
     623                 :            :  *   Buffer to store the result expansion.
     624                 :            :  * @param[in] size
     625                 :            :  *   Buffer size in bytes. If 0, @p buf can be NULL.
     626                 :            :  * @param[in] pattern
     627                 :            :  *   User flow pattern.
     628                 :            :  * @param[in] sq_specs
     629                 :            :  *   Buffer to store sq spec.
     630                 :            :  *
     631                 :            :  * @return
     632                 :            :  *   0 for success and negative value for failure
     633                 :            :  *
     634                 :            :  */
     635                 :            : static int
     636                 :          0 : mlx5_flow_expand_sqn(struct mlx5_flow_expand_sqn *buf, size_t size,
     637                 :            :                      const struct rte_flow_item *pattern,
     638                 :            :                      struct mlx5_rte_flow_item_sq *sq_specs)
     639                 :            : {
     640                 :            :         const struct rte_flow_item *item;
     641                 :            :         bool port_representor = false;
     642                 :            :         size_t user_pattern_size = 0;
     643                 :            :         struct rte_eth_dev *dev;
     644                 :            :         struct mlx5_priv *priv;
     645                 :            :         void *addr = NULL;
     646                 :            :         uint16_t port_id;
     647                 :            :         size_t lsize;
     648                 :            :         int elt = 2;
     649                 :            :         uint16_t i;
     650                 :            : 
     651                 :          0 :         buf->entries = 0;
     652         [ #  # ]:          0 :         for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
     653         [ #  # ]:          0 :                 if (item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
     654                 :          0 :                         const struct rte_flow_item_ethdev *pid_v = item->spec;
     655                 :            : 
     656         [ #  # ]:          0 :                         if (!pid_v)
     657                 :            :                                 return 0;
     658                 :          0 :                         port_id = pid_v->port_id;
     659                 :            :                         port_representor = true;
     660                 :            :                 }
     661                 :          0 :                 user_pattern_size += sizeof(*item);
     662                 :            :         }
     663         [ #  # ]:          0 :         if (!port_representor)
     664                 :            :                 return 0;
     665                 :          0 :         dev = &rte_eth_devices[port_id];
     666                 :          0 :         priv = dev->data->dev_private;
     667                 :          0 :         buf->entry[0].pattern = (void *)&buf->entry[priv->txqs_n];
     668                 :          0 :         lsize = offsetof(struct mlx5_flow_expand_sqn, entry) +
     669                 :          0 :                 sizeof(buf->entry[0]) * priv->txqs_n;
     670         [ #  # ]:          0 :         if (lsize + (user_pattern_size + sizeof(struct rte_flow_item) * elt) * priv->txqs_n > size)
     671                 :            :                 return -EINVAL;
     672                 :            :         addr = buf->entry[0].pattern;
     673         [ #  # ]:          0 :         for (i = 0; i != priv->txqs_n; ++i) {
     674                 :          0 :                 struct rte_flow_item pattern_add[] = {
     675                 :            :                         {
     676                 :            :                                 .type = (enum rte_flow_item_type)
     677                 :            :                                         MLX5_RTE_FLOW_ITEM_TYPE_SQ,
     678                 :          0 :                                 .spec = &sq_specs[i],
     679                 :            :                         },
     680                 :            :                         {
     681                 :            :                                 .type = RTE_FLOW_ITEM_TYPE_END,
     682                 :            :                         },
     683                 :            :                 };
     684                 :          0 :                 struct mlx5_txq_ctrl *txq = mlx5_txq_get(dev, i);
     685                 :            : 
     686         [ #  # ]:          0 :                 if (txq == NULL)
     687                 :          0 :                         return -EINVAL;
     688                 :          0 :                 buf->entry[i].pattern = addr;
     689                 :          0 :                 sq_specs[i].queue = mlx5_txq_get_sqn(txq);
     690                 :          0 :                 mlx5_txq_release(dev, i);
     691                 :            :                 rte_memcpy(addr, pattern, user_pattern_size);
     692         [ #  # ]:          0 :                 addr = (void *)(((uintptr_t)addr) + user_pattern_size);
     693                 :            :                 rte_memcpy(addr, pattern_add, sizeof(struct rte_flow_item) * elt);
     694                 :          0 :                 addr = (void *)(((uintptr_t)addr) + sizeof(struct rte_flow_item) * elt);
     695                 :          0 :                 buf->entries++;
     696                 :            :         }
     697                 :            :         return 0;
     698                 :            : }
     699                 :            : 
     700                 :            : enum mlx5_expansion {
     701                 :            :         MLX5_EXPANSION_ROOT,
     702                 :            :         MLX5_EXPANSION_ROOT_OUTER,
     703                 :            :         MLX5_EXPANSION_OUTER_ETH,
     704                 :            :         MLX5_EXPANSION_OUTER_VLAN,
     705                 :            :         MLX5_EXPANSION_OUTER_IPV4,
     706                 :            :         MLX5_EXPANSION_OUTER_IPV4_UDP,
     707                 :            :         MLX5_EXPANSION_OUTER_IPV4_TCP,
     708                 :            :         MLX5_EXPANSION_OUTER_IPV4_ESP,
     709                 :            :         MLX5_EXPANSION_OUTER_IPV4_ICMP,
     710                 :            :         MLX5_EXPANSION_OUTER_IPV6,
     711                 :            :         MLX5_EXPANSION_OUTER_IPV6_UDP,
     712                 :            :         MLX5_EXPANSION_OUTER_IPV6_TCP,
     713                 :            :         MLX5_EXPANSION_OUTER_IPV6_ESP,
     714                 :            :         MLX5_EXPANSION_OUTER_IPV6_ICMP6,
     715                 :            :         MLX5_EXPANSION_VXLAN,
     716                 :            :         MLX5_EXPANSION_STD_VXLAN,
     717                 :            :         MLX5_EXPANSION_L3_VXLAN,
     718                 :            :         MLX5_EXPANSION_VXLAN_GPE,
     719                 :            :         MLX5_EXPANSION_GRE,
     720                 :            :         MLX5_EXPANSION_NVGRE,
     721                 :            :         MLX5_EXPANSION_GRE_KEY,
     722                 :            :         MLX5_EXPANSION_MPLS,
     723                 :            :         MLX5_EXPANSION_ETH,
     724                 :            :         MLX5_EXPANSION_VLAN,
     725                 :            :         MLX5_EXPANSION_IPV4,
     726                 :            :         MLX5_EXPANSION_IPV4_UDP,
     727                 :            :         MLX5_EXPANSION_IPV4_TCP,
     728                 :            :         MLX5_EXPANSION_IPV4_ESP,
     729                 :            :         MLX5_EXPANSION_IPV4_ICMP,
     730                 :            :         MLX5_EXPANSION_IPV6,
     731                 :            :         MLX5_EXPANSION_IPV6_UDP,
     732                 :            :         MLX5_EXPANSION_IPV6_TCP,
     733                 :            :         MLX5_EXPANSION_IPV6_ESP,
     734                 :            :         MLX5_EXPANSION_IPV6_ICMP6,
     735                 :            :         MLX5_EXPANSION_IPV6_FRAG_EXT,
     736                 :            :         MLX5_EXPANSION_GTP,
     737                 :            :         MLX5_EXPANSION_GENEVE,
     738                 :            : };
     739                 :            : 
     740                 :            : /** Supported expansion of items. */
     741                 :            : static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
     742                 :            :         [MLX5_EXPANSION_ROOT] = {
     743                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
     744                 :            :                                                   MLX5_EXPANSION_IPV4,
     745                 :            :                                                   MLX5_EXPANSION_IPV6),
     746                 :            :                 .type = RTE_FLOW_ITEM_TYPE_END,
     747                 :            :         },
     748                 :            :         [MLX5_EXPANSION_ROOT_OUTER] = {
     749                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_ETH,
     750                 :            :                                                   MLX5_EXPANSION_OUTER_IPV4,
     751                 :            :                                                   MLX5_EXPANSION_OUTER_IPV6),
     752                 :            :                 .type = RTE_FLOW_ITEM_TYPE_END,
     753                 :            :         },
     754                 :            :         [MLX5_EXPANSION_OUTER_ETH] = {
     755                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_VLAN),
     756                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
     757                 :            :                 .rss_types = 0,
     758                 :            :         },
     759                 :            :         [MLX5_EXPANSION_OUTER_VLAN] = {
     760                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_IPV4,
     761                 :            :                                                   MLX5_EXPANSION_OUTER_IPV6),
     762                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
     763                 :            :                 .node_flags = MLX5_EXPANSION_NODE_EXPLICIT,
     764                 :            :         },
     765                 :            :         [MLX5_EXPANSION_OUTER_IPV4] = {
     766                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT
     767                 :            :                         (MLX5_EXPANSION_OUTER_IPV4_UDP,
     768                 :            :                          MLX5_EXPANSION_OUTER_IPV4_TCP,
     769                 :            :                          MLX5_EXPANSION_OUTER_IPV4_ESP,
     770                 :            :                          MLX5_EXPANSION_OUTER_IPV4_ICMP,
     771                 :            :                          MLX5_EXPANSION_GRE,
     772                 :            :                          MLX5_EXPANSION_NVGRE,
     773                 :            :                          MLX5_EXPANSION_IPV4,
     774                 :            :                          MLX5_EXPANSION_IPV6),
     775                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
     776                 :            :                 .rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
     777                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
     778                 :            :         },
     779                 :            :         [MLX5_EXPANSION_OUTER_IPV4_UDP] = {
     780                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VXLAN,
     781                 :            :                                                   MLX5_EXPANSION_VXLAN_GPE,
     782                 :            :                                                   MLX5_EXPANSION_MPLS,
     783                 :            :                                                   MLX5_EXPANSION_GENEVE,
     784                 :            :                                                   MLX5_EXPANSION_GTP),
     785                 :            :                 .type = RTE_FLOW_ITEM_TYPE_UDP,
     786                 :            :                 .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_UDP,
     787                 :            :         },
     788                 :            :         [MLX5_EXPANSION_OUTER_IPV4_TCP] = {
     789                 :            :                 .type = RTE_FLOW_ITEM_TYPE_TCP,
     790                 :            :                 .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
     791                 :            :         },
     792                 :            :         [MLX5_EXPANSION_OUTER_IPV4_ESP] = {
     793                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ESP,
     794                 :            :                 .rss_types = RTE_ETH_RSS_ESP,
     795                 :            :         },
     796                 :            :         [MLX5_EXPANSION_OUTER_IPV4_ICMP] = {
     797                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ICMP,
     798                 :            :         },
     799                 :            :         [MLX5_EXPANSION_OUTER_IPV6] = {
     800                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT
     801                 :            :                         (MLX5_EXPANSION_OUTER_IPV6_UDP,
     802                 :            :                          MLX5_EXPANSION_OUTER_IPV6_TCP,
     803                 :            :                          MLX5_EXPANSION_OUTER_IPV6_ESP,
     804                 :            :                          MLX5_EXPANSION_OUTER_IPV6_ICMP6,
     805                 :            :                          MLX5_EXPANSION_IPV4,
     806                 :            :                          MLX5_EXPANSION_IPV6,
     807                 :            :                          MLX5_EXPANSION_GRE,
     808                 :            :                          MLX5_EXPANSION_NVGRE),
     809                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV6,
     810                 :            :                 .rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
     811                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
     812                 :            :         },
     813                 :            :         [MLX5_EXPANSION_OUTER_IPV6_UDP] = {
     814                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VXLAN,
     815                 :            :                                                   MLX5_EXPANSION_VXLAN_GPE,
     816                 :            :                                                   MLX5_EXPANSION_MPLS,
     817                 :            :                                                   MLX5_EXPANSION_GENEVE,
     818                 :            :                                                   MLX5_EXPANSION_GTP),
     819                 :            :                 .type = RTE_FLOW_ITEM_TYPE_UDP,
     820                 :            :                 .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_UDP,
     821                 :            :         },
     822                 :            :         [MLX5_EXPANSION_OUTER_IPV6_TCP] = {
     823                 :            :                 .type = RTE_FLOW_ITEM_TYPE_TCP,
     824                 :            :                 .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
     825                 :            :         },
     826                 :            :         [MLX5_EXPANSION_OUTER_IPV6_ESP] = {
     827                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ESP,
     828                 :            :                 .rss_types = RTE_ETH_RSS_ESP,
     829                 :            :         },
     830                 :            :         [MLX5_EXPANSION_OUTER_IPV6_ICMP6] = {
     831                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ICMP6,
     832                 :            :         },
     833                 :            :         [MLX5_EXPANSION_VXLAN] = {
     834                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
     835                 :            :                                                   MLX5_EXPANSION_IPV4,
     836                 :            :                                                   MLX5_EXPANSION_IPV6),
     837                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
     838                 :            :         },
     839                 :            :         [MLX5_EXPANSION_STD_VXLAN] = {
     840                 :            :                         .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH),
     841                 :            :                                         .type = RTE_FLOW_ITEM_TYPE_VXLAN,
     842                 :            :         },
     843                 :            :         [MLX5_EXPANSION_L3_VXLAN] = {
     844                 :            :                         .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
     845                 :            :                                         MLX5_EXPANSION_IPV6),
     846                 :            :                                         .type = RTE_FLOW_ITEM_TYPE_VXLAN,
     847                 :            :         },
     848                 :            :         [MLX5_EXPANSION_VXLAN_GPE] = {
     849                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
     850                 :            :                                                   MLX5_EXPANSION_IPV4,
     851                 :            :                                                   MLX5_EXPANSION_IPV6),
     852                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VXLAN_GPE,
     853                 :            :         },
     854                 :            :         [MLX5_EXPANSION_GRE] = {
     855                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
     856                 :            :                                                   MLX5_EXPANSION_IPV4,
     857                 :            :                                                   MLX5_EXPANSION_IPV6,
     858                 :            :                                                   MLX5_EXPANSION_GRE_KEY,
     859                 :            :                                                   MLX5_EXPANSION_MPLS),
     860                 :            :                 .type = RTE_FLOW_ITEM_TYPE_GRE,
     861                 :            :         },
     862                 :            :         [MLX5_EXPANSION_GRE_KEY] = {
     863                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
     864                 :            :                                                   MLX5_EXPANSION_IPV6,
     865                 :            :                                                   MLX5_EXPANSION_MPLS),
     866                 :            :                 .type = RTE_FLOW_ITEM_TYPE_GRE_KEY,
     867                 :            :                 .node_flags = MLX5_EXPANSION_NODE_OPTIONAL,
     868                 :            :         },
     869                 :            :         [MLX5_EXPANSION_NVGRE] = {
     870                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH),
     871                 :            :                 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
     872                 :            :         },
     873                 :            :         [MLX5_EXPANSION_MPLS] = {
     874                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
     875                 :            :                                                   MLX5_EXPANSION_IPV6,
     876                 :            :                                                   MLX5_EXPANSION_ETH),
     877                 :            :                 .type = RTE_FLOW_ITEM_TYPE_MPLS,
     878                 :            :                 .node_flags = MLX5_EXPANSION_NODE_OPTIONAL,
     879                 :            :         },
     880                 :            :         [MLX5_EXPANSION_ETH] = {
     881                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VLAN),
     882                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
     883                 :            :         },
     884                 :            :         [MLX5_EXPANSION_VLAN] = {
     885                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
     886                 :            :                                                   MLX5_EXPANSION_IPV6),
     887                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
     888                 :            :                 .node_flags = MLX5_EXPANSION_NODE_EXPLICIT,
     889                 :            :         },
     890                 :            :         [MLX5_EXPANSION_IPV4] = {
     891                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP,
     892                 :            :                                                   MLX5_EXPANSION_IPV4_TCP,
     893                 :            :                                                   MLX5_EXPANSION_IPV4_ESP,
     894                 :            :                                                   MLX5_EXPANSION_IPV4_ICMP),
     895                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
     896                 :            :                 .rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
     897                 :            :                         RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
     898                 :            :         },
     899                 :            :         [MLX5_EXPANSION_IPV4_UDP] = {
     900                 :            :                 .type = RTE_FLOW_ITEM_TYPE_UDP,
     901                 :            :                 .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_UDP,
     902                 :            :         },
     903                 :            :         [MLX5_EXPANSION_IPV4_TCP] = {
     904                 :            :                 .type = RTE_FLOW_ITEM_TYPE_TCP,
     905                 :            :                 .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
     906                 :            :         },
     907                 :            :         [MLX5_EXPANSION_IPV4_ESP] = {
     908                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ESP,
     909                 :            :                 .rss_types = RTE_ETH_RSS_ESP,
     910                 :            :         },
     911                 :            :         [MLX5_EXPANSION_IPV4_ICMP] = {
     912                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ICMP,
     913                 :            :         },
     914                 :            :         [MLX5_EXPANSION_IPV6] = {
     915                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP,
     916                 :            :                                                   MLX5_EXPANSION_IPV6_TCP,
     917                 :            :                                                   MLX5_EXPANSION_IPV6_ESP,
     918                 :            :                                                   MLX5_EXPANSION_IPV6_ICMP6,
     919                 :            :                                                   MLX5_EXPANSION_IPV6_FRAG_EXT),
     920                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV6,
     921                 :            :                 .rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
     922                 :            :                         RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
     923                 :            :         },
     924                 :            :         [MLX5_EXPANSION_IPV6_UDP] = {
     925                 :            :                 .type = RTE_FLOW_ITEM_TYPE_UDP,
     926                 :            :                 .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_UDP,
     927                 :            :         },
     928                 :            :         [MLX5_EXPANSION_IPV6_TCP] = {
     929                 :            :                 .type = RTE_FLOW_ITEM_TYPE_TCP,
     930                 :            :                 .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
     931                 :            :         },
     932                 :            :         [MLX5_EXPANSION_IPV6_ESP] = {
     933                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ESP,
     934                 :            :                 .rss_types = RTE_ETH_RSS_ESP,
     935                 :            :         },
     936                 :            :         [MLX5_EXPANSION_IPV6_FRAG_EXT] = {
     937                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT,
     938                 :            :         },
     939                 :            :         [MLX5_EXPANSION_IPV6_ICMP6] = {
     940                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ICMP6,
     941                 :            :         },
     942                 :            :         [MLX5_EXPANSION_GTP] = {
     943                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
     944                 :            :                                                   MLX5_EXPANSION_IPV6),
     945                 :            :                 .type = RTE_FLOW_ITEM_TYPE_GTP,
     946                 :            :         },
     947                 :            :         [MLX5_EXPANSION_GENEVE] = {
     948                 :            :                 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
     949                 :            :                                                   MLX5_EXPANSION_IPV4,
     950                 :            :                                                   MLX5_EXPANSION_IPV6),
     951                 :            :                 .type = RTE_FLOW_ITEM_TYPE_GENEVE,
     952                 :            :         },
     953                 :            : };
     954                 :            : 
     955                 :            : static struct rte_flow_action_handle *
     956                 :            : mlx5_action_handle_create(struct rte_eth_dev *dev,
     957                 :            :                           const struct rte_flow_indir_action_conf *conf,
     958                 :            :                           const struct rte_flow_action *action,
     959                 :            :                           struct rte_flow_error *error);
     960                 :            : static int mlx5_action_handle_destroy
     961                 :            :                                 (struct rte_eth_dev *dev,
     962                 :            :                                  struct rte_flow_action_handle *handle,
     963                 :            :                                  struct rte_flow_error *error);
     964                 :            : static int mlx5_action_handle_update
     965                 :            :                                 (struct rte_eth_dev *dev,
     966                 :            :                                  struct rte_flow_action_handle *handle,
     967                 :            :                                  const void *update,
     968                 :            :                                  struct rte_flow_error *error);
     969                 :            : static int mlx5_action_handle_query
     970                 :            :                                 (struct rte_eth_dev *dev,
     971                 :            :                                  const struct rte_flow_action_handle *handle,
     972                 :            :                                  void *data,
     973                 :            :                                  struct rte_flow_error *error);
     974                 :            : static int
     975                 :            : mlx5_flow_tunnel_decap_set(struct rte_eth_dev *dev,
     976                 :            :                     struct rte_flow_tunnel *app_tunnel,
     977                 :            :                     struct rte_flow_action **actions,
     978                 :            :                     uint32_t *num_of_actions,
     979                 :            :                     struct rte_flow_error *error);
     980                 :            : static int
     981                 :            : mlx5_flow_tunnel_match(struct rte_eth_dev *dev,
     982                 :            :                        struct rte_flow_tunnel *app_tunnel,
     983                 :            :                        struct rte_flow_item **items,
     984                 :            :                        uint32_t *num_of_items,
     985                 :            :                        struct rte_flow_error *error);
     986                 :            : static int
     987                 :            : mlx5_flow_tunnel_item_release(struct rte_eth_dev *dev,
     988                 :            :                               struct rte_flow_item *pmd_items,
     989                 :            :                               uint32_t num_items, struct rte_flow_error *err);
     990                 :            : static int
     991                 :            : mlx5_flow_tunnel_action_release(struct rte_eth_dev *dev,
     992                 :            :                                 struct rte_flow_action *pmd_actions,
     993                 :            :                                 uint32_t num_actions,
     994                 :            :                                 struct rte_flow_error *err);
     995                 :            : static int
     996                 :            : mlx5_flow_tunnel_get_restore_info(struct rte_eth_dev *dev,
     997                 :            :                                   struct rte_mbuf *m,
     998                 :            :                                   struct rte_flow_restore_info *info,
     999                 :            :                                   struct rte_flow_error *err);
    1000                 :            : static struct rte_flow_item_flex_handle *
    1001                 :            : mlx5_flow_flex_item_create(struct rte_eth_dev *dev,
    1002                 :            :                            const struct rte_flow_item_flex_conf *conf,
    1003                 :            :                            struct rte_flow_error *error);
    1004                 :            : static int
    1005                 :            : mlx5_flow_flex_item_release(struct rte_eth_dev *dev,
    1006                 :            :                             const struct rte_flow_item_flex_handle *handle,
    1007                 :            :                             struct rte_flow_error *error);
    1008                 :            : static int
    1009                 :            : mlx5_flow_info_get(struct rte_eth_dev *dev,
    1010                 :            :                    struct rte_flow_port_info *port_info,
    1011                 :            :                    struct rte_flow_queue_info *queue_info,
    1012                 :            :                    struct rte_flow_error *error);
    1013                 :            : static int
    1014                 :            : mlx5_flow_port_configure(struct rte_eth_dev *dev,
    1015                 :            :                          const struct rte_flow_port_attr *port_attr,
    1016                 :            :                          uint16_t nb_queue,
    1017                 :            :                          const struct rte_flow_queue_attr *queue_attr[],
    1018                 :            :                          struct rte_flow_error *err);
    1019                 :            : 
    1020                 :            : static struct rte_flow_pattern_template *
    1021                 :            : mlx5_flow_pattern_template_create(struct rte_eth_dev *dev,
    1022                 :            :                 const struct rte_flow_pattern_template_attr *attr,
    1023                 :            :                 const struct rte_flow_item items[],
    1024                 :            :                 struct rte_flow_error *error);
    1025                 :            : 
    1026                 :            : static int
    1027                 :            : mlx5_flow_pattern_template_destroy(struct rte_eth_dev *dev,
    1028                 :            :                                    struct rte_flow_pattern_template *template,
    1029                 :            :                                    struct rte_flow_error *error);
    1030                 :            : static struct rte_flow_actions_template *
    1031                 :            : mlx5_flow_actions_template_create(struct rte_eth_dev *dev,
    1032                 :            :                         const struct rte_flow_actions_template_attr *attr,
    1033                 :            :                         const struct rte_flow_action actions[],
    1034                 :            :                         const struct rte_flow_action masks[],
    1035                 :            :                         struct rte_flow_error *error);
    1036                 :            : static int
    1037                 :            : mlx5_flow_actions_template_destroy(struct rte_eth_dev *dev,
    1038                 :            :                                    struct rte_flow_actions_template *template,
    1039                 :            :                                    struct rte_flow_error *error);
    1040                 :            : 
    1041                 :            : static struct rte_flow_template_table *
    1042                 :            : mlx5_flow_table_create(struct rte_eth_dev *dev,
    1043                 :            :                        const struct rte_flow_template_table_attr *attr,
    1044                 :            :                        struct rte_flow_pattern_template *item_templates[],
    1045                 :            :                        uint8_t nb_item_templates,
    1046                 :            :                        struct rte_flow_actions_template *action_templates[],
    1047                 :            :                        uint8_t nb_action_templates,
    1048                 :            :                        struct rte_flow_error *error);
    1049                 :            : static int
    1050                 :            : mlx5_flow_table_destroy(struct rte_eth_dev *dev,
    1051                 :            :                         struct rte_flow_template_table *table,
    1052                 :            :                         struct rte_flow_error *error);
    1053                 :            : static int
    1054                 :            : mlx5_flow_group_set_miss_actions(struct rte_eth_dev *dev,
    1055                 :            :                                  uint32_t group_id,
    1056                 :            :                                  const struct rte_flow_group_attr *attr,
    1057                 :            :                                  const struct rte_flow_action actions[],
    1058                 :            :                                  struct rte_flow_error *error);
    1059                 :            : 
    1060                 :            : static int
    1061                 :            : mlx5_action_handle_query_update(struct rte_eth_dev *dev,
    1062                 :            :                                 struct rte_flow_action_handle *handle,
    1063                 :            :                                 const void *update, void *query,
    1064                 :            :                                 enum rte_flow_query_update_mode qu_mode,
    1065                 :            :                                 struct rte_flow_error *error);
    1066                 :            : 
    1067                 :            : static struct rte_flow_action_list_handle *
    1068                 :            : mlx5_action_list_handle_create(struct rte_eth_dev *dev,
    1069                 :            :                                const struct rte_flow_indir_action_conf *conf,
    1070                 :            :                                const struct rte_flow_action *actions,
    1071                 :            :                                struct rte_flow_error *error);
    1072                 :            : 
    1073                 :            : static int
    1074                 :            : mlx5_action_list_handle_destroy(struct rte_eth_dev *dev,
    1075                 :            :                                 struct rte_flow_action_list_handle *handle,
    1076                 :            :                                 struct rte_flow_error *error);
    1077                 :            : 
    1078                 :            : static int
    1079                 :            : mlx5_flow_action_list_handle_query_update(struct rte_eth_dev *dev,
    1080                 :            :                                           const
    1081                 :            :                                           struct rte_flow_action_list_handle *handle,
    1082                 :            :                                           const void **update, void **query,
    1083                 :            :                                           enum rte_flow_query_update_mode mode,
    1084                 :            :                                           struct rte_flow_error *error);
    1085                 :            : 
    1086                 :            : static int
    1087                 :            : mlx5_flow_calc_table_hash(struct rte_eth_dev *dev,
    1088                 :            :                           const struct rte_flow_template_table *table,
    1089                 :            :                           const struct rte_flow_item pattern[],
    1090                 :            :                           uint8_t pattern_template_index,
    1091                 :            :                           uint32_t *hash, struct rte_flow_error *error);
    1092                 :            : static int
    1093                 :            : mlx5_flow_calc_encap_hash(struct rte_eth_dev *dev,
    1094                 :            :                           const struct rte_flow_item pattern[],
    1095                 :            :                           enum rte_flow_encap_hash_field dest_field,
    1096                 :            :                           uint8_t *hash,
    1097                 :            :                           struct rte_flow_error *error);
    1098                 :            : 
    1099                 :            : static int
    1100                 :            : mlx5_template_table_resize(struct rte_eth_dev *dev,
    1101                 :            :                            struct rte_flow_template_table *table,
    1102                 :            :                            uint32_t nb_rules, struct rte_flow_error *error);
    1103                 :            : static int
    1104                 :            : mlx5_flow_async_update_resized(struct rte_eth_dev *dev, uint32_t queue,
    1105                 :            :                                const struct rte_flow_op_attr *attr,
    1106                 :            :                                struct rte_flow *rule, void *user_data,
    1107                 :            :                                struct rte_flow_error *error);
    1108                 :            : static int
    1109                 :            : mlx5_table_resize_complete(struct rte_eth_dev *dev,
    1110                 :            :                            struct rte_flow_template_table *table,
    1111                 :            :                            struct rte_flow_error *error);
    1112                 :            : 
    1113                 :            : static const struct rte_flow_ops mlx5_flow_ops = {
    1114                 :            :         .validate = mlx5_flow_validate,
    1115                 :            :         .create = mlx5_flow_create,
    1116                 :            :         .destroy = mlx5_flow_destroy,
    1117                 :            :         .flush = mlx5_flow_flush,
    1118                 :            :         .isolate = mlx5_flow_isolate,
    1119                 :            :         .query = mlx5_flow_query,
    1120                 :            :         .dev_dump = mlx5_flow_dev_dump,
    1121                 :            :         .get_q_aged_flows = mlx5_flow_get_q_aged_flows,
    1122                 :            :         .get_aged_flows = mlx5_flow_get_aged_flows,
    1123                 :            :         .action_handle_create = mlx5_action_handle_create,
    1124                 :            :         .action_handle_destroy = mlx5_action_handle_destroy,
    1125                 :            :         .action_handle_update = mlx5_action_handle_update,
    1126                 :            :         .action_handle_query = mlx5_action_handle_query,
    1127                 :            :         .action_handle_query_update = mlx5_action_handle_query_update,
    1128                 :            :         .action_list_handle_create = mlx5_action_list_handle_create,
    1129                 :            :         .action_list_handle_destroy = mlx5_action_list_handle_destroy,
    1130                 :            :         .tunnel_decap_set = mlx5_flow_tunnel_decap_set,
    1131                 :            :         .tunnel_match = mlx5_flow_tunnel_match,
    1132                 :            :         .tunnel_action_decap_release = mlx5_flow_tunnel_action_release,
    1133                 :            :         .tunnel_item_release = mlx5_flow_tunnel_item_release,
    1134                 :            :         .get_restore_info = mlx5_flow_tunnel_get_restore_info,
    1135                 :            :         .flex_item_create = mlx5_flow_flex_item_create,
    1136                 :            :         .flex_item_release = mlx5_flow_flex_item_release,
    1137                 :            :         .info_get = mlx5_flow_info_get,
    1138                 :            :         .pick_transfer_proxy = mlx5_flow_pick_transfer_proxy,
    1139                 :            :         .configure = mlx5_flow_port_configure,
    1140                 :            :         .pattern_template_create = mlx5_flow_pattern_template_create,
    1141                 :            :         .pattern_template_destroy = mlx5_flow_pattern_template_destroy,
    1142                 :            :         .actions_template_create = mlx5_flow_actions_template_create,
    1143                 :            :         .actions_template_destroy = mlx5_flow_actions_template_destroy,
    1144                 :            :         .template_table_create = mlx5_flow_table_create,
    1145                 :            :         .template_table_destroy = mlx5_flow_table_destroy,
    1146                 :            :         .group_set_miss_actions = mlx5_flow_group_set_miss_actions,
    1147                 :            :         .action_list_handle_query_update =
    1148                 :            :                 mlx5_flow_action_list_handle_query_update,
    1149                 :            :         .flow_calc_table_hash = mlx5_flow_calc_table_hash,
    1150                 :            :         .flow_calc_encap_hash = mlx5_flow_calc_encap_hash,
    1151                 :            :         .flow_template_table_resize = mlx5_template_table_resize,
    1152                 :            :         .flow_update_resized = mlx5_flow_async_update_resized,
    1153                 :            :         .flow_template_table_resize_complete = mlx5_table_resize_complete,
    1154                 :            : };
    1155                 :            : 
    1156                 :            : /* Tunnel information. */
    1157                 :            : struct mlx5_flow_tunnel_info {
    1158                 :            :         uint64_t tunnel; /**< Tunnel bit (see MLX5_FLOW_*). */
    1159                 :            :         uint32_t ptype; /**< Tunnel Ptype (see RTE_PTYPE_*). */
    1160                 :            : };
    1161                 :            : 
    1162                 :            : static struct mlx5_flow_tunnel_info tunnels_info[] = {
    1163                 :            :         {
    1164                 :            :                 .tunnel = MLX5_FLOW_LAYER_VXLAN,
    1165                 :            :                 .ptype = RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_L4_UDP,
    1166                 :            :         },
    1167                 :            :         {
    1168                 :            :                 .tunnel = MLX5_FLOW_LAYER_GENEVE,
    1169                 :            :                 .ptype = RTE_PTYPE_TUNNEL_GENEVE | RTE_PTYPE_L4_UDP,
    1170                 :            :         },
    1171                 :            :         {
    1172                 :            :                 .tunnel = MLX5_FLOW_LAYER_VXLAN_GPE,
    1173                 :            :                 .ptype = RTE_PTYPE_TUNNEL_VXLAN_GPE | RTE_PTYPE_L4_UDP,
    1174                 :            :         },
    1175                 :            :         {
    1176                 :            :                 .tunnel = MLX5_FLOW_LAYER_GRE,
    1177                 :            :                 .ptype = RTE_PTYPE_TUNNEL_GRE,
    1178                 :            :         },
    1179                 :            :         {
    1180                 :            :                 .tunnel = MLX5_FLOW_LAYER_MPLS | MLX5_FLOW_LAYER_OUTER_L4_UDP,
    1181                 :            :                 .ptype = RTE_PTYPE_TUNNEL_MPLS_IN_UDP | RTE_PTYPE_L4_UDP,
    1182                 :            :         },
    1183                 :            :         {
    1184                 :            :                 .tunnel = MLX5_FLOW_LAYER_MPLS,
    1185                 :            :                 .ptype = RTE_PTYPE_TUNNEL_MPLS_IN_GRE,
    1186                 :            :         },
    1187                 :            :         {
    1188                 :            :                 .tunnel = MLX5_FLOW_LAYER_NVGRE,
    1189                 :            :                 .ptype = RTE_PTYPE_TUNNEL_NVGRE,
    1190                 :            :         },
    1191                 :            :         {
    1192                 :            :                 .tunnel = MLX5_FLOW_LAYER_IPIP,
    1193                 :            :                 .ptype = RTE_PTYPE_TUNNEL_IP,
    1194                 :            :         },
    1195                 :            :         {
    1196                 :            :                 .tunnel = MLX5_FLOW_LAYER_IPV6_ENCAP,
    1197                 :            :                 .ptype = RTE_PTYPE_TUNNEL_IP,
    1198                 :            :         },
    1199                 :            :         {
    1200                 :            :                 .tunnel = MLX5_FLOW_LAYER_GTP,
    1201                 :            :                 .ptype = RTE_PTYPE_TUNNEL_GTPU,
    1202                 :            :         },
    1203                 :            : };
    1204                 :            : 
    1205                 :            : 
    1206                 :            : 
    1207                 :            : /**
    1208                 :            :  * Translate tag ID to register.
    1209                 :            :  *
    1210                 :            :  * @param[in] dev
    1211                 :            :  *   Pointer to the Ethernet device structure.
    1212                 :            :  * @param[in] feature
    1213                 :            :  *   The feature that request the register.
    1214                 :            :  * @param[in] id
    1215                 :            :  *   The request register ID.
    1216                 :            :  * @param[out] error
    1217                 :            :  *   Error description in case of any.
    1218                 :            :  *
    1219                 :            :  * @return
    1220                 :            :  *   The request register on success, a negative errno
    1221                 :            :  *   value otherwise and rte_errno is set.
    1222                 :            :  */
    1223                 :            : int
    1224                 :          0 : mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
    1225                 :            :                      enum mlx5_feature_name feature,
    1226                 :            :                      uint32_t id,
    1227                 :            :                      struct rte_flow_error *error)
    1228                 :            : {
    1229                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1230                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    1231                 :            :         struct mlx5_dev_registers *reg = &priv->sh->registers;
    1232                 :            :         enum modify_reg start_reg;
    1233                 :            :         bool skip_mtr_reg = false;
    1234                 :            : 
    1235   [ #  #  #  #  :          0 :         switch (feature) {
          #  #  #  #  #  
                   #  # ]
    1236                 :            :         case MLX5_HAIRPIN_RX:
    1237                 :            :                 return REG_B;
    1238                 :          0 :         case MLX5_HAIRPIN_TX:
    1239                 :          0 :                 return REG_A;
    1240                 :          0 :         case MLX5_METADATA_RX:
    1241   [ #  #  #  #  :          0 :                 switch (config->dv_xmeta_en) {
                      # ]
    1242                 :            :                 case MLX5_XMETA_MODE_LEGACY:
    1243                 :            :                         return REG_B;
    1244                 :          0 :                 case MLX5_XMETA_MODE_META16:
    1245                 :          0 :                         return REG_C_0;
    1246                 :          0 :                 case MLX5_XMETA_MODE_META32:
    1247                 :          0 :                         return REG_C_1;
    1248                 :          0 :                 case MLX5_XMETA_MODE_META32_HWS:
    1249                 :          0 :                         return REG_C_1;
    1250                 :            :                 }
    1251                 :            :                 break;
    1252                 :          0 :         case MLX5_METADATA_TX:
    1253         [ #  # ]:          0 :                 if (config->dv_flow_en == 2 && config->dv_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {
    1254                 :            :                         return REG_C_1;
    1255                 :            :                 } else {
    1256                 :          0 :                         return REG_A;
    1257                 :            :                 }
    1258                 :          0 :         case MLX5_METADATA_FDB:
    1259   [ #  #  #  #  :          0 :                 switch (config->dv_xmeta_en) {
                      # ]
    1260                 :            :                 case MLX5_XMETA_MODE_LEGACY:
    1261                 :            :                         return REG_NON;
    1262                 :          0 :                 case MLX5_XMETA_MODE_META16:
    1263                 :          0 :                         return REG_C_0;
    1264                 :          0 :                 case MLX5_XMETA_MODE_META32:
    1265                 :          0 :                         return REG_C_1;
    1266                 :          0 :                 case MLX5_XMETA_MODE_META32_HWS:
    1267                 :          0 :                         return REG_C_1;
    1268                 :            :                 }
    1269                 :            :                 break;
    1270                 :          0 :         case MLX5_FLOW_MARK:
    1271   [ #  #  #  # ]:          0 :                 switch (config->dv_xmeta_en) {
    1272                 :            :                 case MLX5_XMETA_MODE_LEGACY:
    1273                 :            :                 case MLX5_XMETA_MODE_META32_HWS:
    1274                 :            :                         return REG_NON;
    1275                 :          0 :                 case MLX5_XMETA_MODE_META16:
    1276                 :          0 :                         return REG_C_1;
    1277                 :          0 :                 case MLX5_XMETA_MODE_META32:
    1278                 :          0 :                         return REG_C_0;
    1279                 :            :                 }
    1280                 :            :                 break;
    1281                 :          0 :         case MLX5_MTR_ID:
    1282                 :            :                 /*
    1283                 :            :                  * If meter color and meter id share one register, flow match
    1284                 :            :                  * should use the meter color register for match.
    1285                 :            :                  */
    1286         [ #  # ]:          0 :                 if (priv->mtr_reg_share)
    1287                 :          0 :                         return reg->aso_reg;
    1288                 :            :                 else
    1289         [ #  # ]:          0 :                         return reg->aso_reg != REG_C_2 ? REG_C_2 :
    1290                 :            :                                REG_C_3;
    1291                 :          0 :         case MLX5_MTR_COLOR:
    1292                 :            :         case MLX5_ASO_FLOW_HIT:
    1293                 :            :         case MLX5_ASO_CONNTRACK:
    1294                 :            :         case MLX5_SAMPLE_ID:
    1295                 :            :                 /* All features use the same REG_C. */
    1296                 :            :                 MLX5_ASSERT(reg->aso_reg != REG_NON);
    1297                 :          0 :                 return reg->aso_reg;
    1298                 :          0 :         case MLX5_COPY_MARK:
    1299                 :            :                 /*
    1300                 :            :                  * Metadata COPY_MARK register using is in meter suffix sub
    1301                 :            :                  * flow while with meter. It's safe to share the same register.
    1302                 :            :                  */
    1303         [ #  # ]:          0 :                 return reg->aso_reg != REG_C_2 ? REG_C_2 : REG_C_3;
    1304                 :          0 :         case MLX5_APP_TAG:
    1305                 :            :                 /*
    1306                 :            :                  * If meter is enable, it will engage the register for color
    1307                 :            :                  * match and flow match. If meter color match is not using the
    1308                 :            :                  * REG_C_2, need to skip the REG_C_x be used by meter color
    1309                 :            :                  * match.
    1310                 :            :                  * If meter is disable, free to use all available registers.
    1311                 :            :                  */
    1312         [ #  # ]:          0 :                 start_reg = reg->aso_reg != REG_C_2 ? REG_C_2 :
    1313         [ #  # ]:          0 :                             (priv->mtr_reg_share ? REG_C_3 : REG_C_4);
    1314   [ #  #  #  # ]:          0 :                 skip_mtr_reg = !!(priv->mtr_en && start_reg == REG_C_2);
    1315         [ #  # ]:          0 :                 if (id > (uint32_t)(REG_C_7 - start_reg))
    1316                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    1317                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    1318                 :            :                                                   NULL, "invalid tag id");
    1319         [ #  # ]:          0 :                 if (priv->sh->flow_mreg_c[id + start_reg - REG_C_0] == REG_NON)
    1320                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    1321                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    1322                 :            :                                                   NULL, "unsupported tag id");
    1323                 :            :                 /*
    1324                 :            :                  * This case means meter is using the REG_C_x great than 2.
    1325                 :            :                  * Take care not to conflict with meter color REG_C_x.
    1326                 :            :                  * If the available index REG_C_y >= REG_C_x, skip the
    1327                 :            :                  * color register.
    1328                 :            :                  */
    1329   [ #  #  #  # ]:          0 :                 if (skip_mtr_reg && priv->sh->flow_mreg_c
    1330                 :            :                     [id + start_reg - REG_C_0] >= reg->aso_reg) {
    1331         [ #  # ]:          0 :                         if (id >= (uint32_t)(REG_C_7 - start_reg))
    1332                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    1333                 :            :                                                        RTE_FLOW_ERROR_TYPE_ITEM,
    1334                 :            :                                                         NULL, "invalid tag id");
    1335                 :          0 :                         if (priv->sh->flow_mreg_c
    1336         [ #  # ]:          0 :                             [id + 1 + start_reg - REG_C_0] != REG_NON)
    1337                 :            :                                 return priv->sh->flow_mreg_c
    1338                 :          0 :                                                [id + 1 + start_reg - REG_C_0];
    1339                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    1340                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    1341                 :            :                                                   NULL, "unsupported tag id");
    1342                 :            :                 }
    1343                 :          0 :                 return priv->sh->flow_mreg_c[id + start_reg - REG_C_0];
    1344                 :            :         }
    1345                 :            :         MLX5_ASSERT(false);
    1346                 :          0 :         return rte_flow_error_set(error, EINVAL,
    1347                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1348                 :            :                                   NULL, "invalid feature name");
    1349                 :            : }
    1350                 :            : 
    1351                 :            : /**
    1352                 :            :  * Check extensive flow metadata register support.
    1353                 :            :  *
    1354                 :            :  * @param dev
    1355                 :            :  *   Pointer to rte_eth_dev structure.
    1356                 :            :  *
    1357                 :            :  * @return
    1358                 :            :  *   True if device supports extensive flow metadata register, otherwise false.
    1359                 :            :  */
    1360                 :            : bool
    1361                 :          0 : mlx5_flow_ext_mreg_supported(struct rte_eth_dev *dev)
    1362                 :            : {
    1363                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1364                 :            : 
    1365                 :            :         /*
    1366                 :            :          * Having available reg_c can be regarded inclusively as supporting
    1367                 :            :          * extensive flow metadata register, which could mean,
    1368                 :            :          * - metadata register copy action by modify header.
    1369                 :            :          * - 16 modify header actions is supported.
    1370                 :            :          * - reg_c's are preserved across different domain (FDB and NIC) on
    1371                 :            :          *   packet loopback by flow lookup miss.
    1372                 :            :          */
    1373                 :          0 :         return priv->sh->flow_mreg_c[2] != REG_NON;
    1374                 :            : }
    1375                 :            : 
    1376                 :            : /**
    1377                 :            :  * Get the lowest priority.
    1378                 :            :  *
    1379                 :            :  * @param[in] dev
    1380                 :            :  *   Pointer to the Ethernet device structure.
    1381                 :            :  * @param[in] attributes
    1382                 :            :  *   Pointer to device flow rule attributes.
    1383                 :            :  *
    1384                 :            :  * @return
    1385                 :            :  *   The value of lowest priority of flow.
    1386                 :            :  */
    1387                 :            : uint32_t
    1388                 :          0 : mlx5_get_lowest_priority(struct rte_eth_dev *dev,
    1389                 :            :                           const struct rte_flow_attr *attr)
    1390                 :            : {
    1391                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1392                 :            : 
    1393   [ #  #  #  #  :          0 :         if (!attr->group && !(attr->transfer && priv->fdb_def_rule))
                   #  # ]
    1394                 :          0 :                 return priv->sh->flow_max_priority - 2;
    1395                 :            :         return MLX5_NON_ROOT_FLOW_MAX_PRIO - 1;
    1396                 :            : }
    1397                 :            : 
    1398                 :            : /**
    1399                 :            :  * Calculate matcher priority of the flow.
    1400                 :            :  *
    1401                 :            :  * @param[in] dev
    1402                 :            :  *   Pointer to the Ethernet device structure.
    1403                 :            :  * @param[in] attr
    1404                 :            :  *   Pointer to device flow rule attributes.
    1405                 :            :  * @param[in] subpriority
    1406                 :            :  *   The priority based on the items.
    1407                 :            :  * @param[in] external
    1408                 :            :  *   Flow is user flow.
    1409                 :            :  * @return
    1410                 :            :  *   The matcher priority of the flow.
    1411                 :            :  */
    1412                 :            : uint16_t
    1413                 :          0 : mlx5_get_matcher_priority(struct rte_eth_dev *dev,
    1414                 :            :                           const struct rte_flow_attr *attr,
    1415                 :            :                           uint32_t subpriority, bool external)
    1416                 :            : {
    1417                 :          0 :         uint16_t priority = (uint16_t)attr->priority;
    1418                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1419                 :            : 
    1420                 :            :         /* NIC root rules */
    1421   [ #  #  #  # ]:          0 :         if (!attr->group && !attr->transfer) {
    1422         [ #  # ]:          0 :                 if (attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR)
    1423                 :          0 :                         priority = priv->sh->flow_max_priority - 1;
    1424                 :          0 :                 return mlx5_os_flow_adjust_priority(dev, priority, subpriority);
    1425                 :            :         /* FDB root rules */
    1426   [ #  #  #  #  :          0 :         } else if (attr->transfer && (!external || !priv->fdb_def_rule) &&
             #  #  #  # ]
    1427         [ #  # ]:          0 :                    attr->group == 0 &&
    1428                 :            :                    attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) {
    1429                 :          0 :                 return (priv->sh->flow_max_priority - 1) * 3;
    1430                 :            :         }
    1431         [ #  # ]:          0 :         if (attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR)
    1432                 :            :                 priority = MLX5_NON_ROOT_FLOW_MAX_PRIO;
    1433                 :          0 :         return priority * 3 + subpriority;
    1434                 :            : }
    1435                 :            : 
    1436                 :            : /**
    1437                 :            :  * Verify the @p item specifications (spec, last, mask) are compatible with the
    1438                 :            :  * NIC capabilities.
    1439                 :            :  *
    1440                 :            :  * @param[in] item
    1441                 :            :  *   Item specification.
    1442                 :            :  * @param[in] mask
    1443                 :            :  *   @p item->mask or flow default bit-masks.
    1444                 :            :  * @param[in] nic_mask
    1445                 :            :  *   Bit-masks covering supported fields by the NIC to compare with user mask.
    1446                 :            :  * @param[in] size
    1447                 :            :  *   Bit-masks size in bytes.
    1448                 :            :  * @param[in] range_accepted
    1449                 :            :  *   True if range of values is accepted for specific fields, false otherwise.
    1450                 :            :  * @param[out] error
    1451                 :            :  *   Pointer to error structure.
    1452                 :            :  *
    1453                 :            :  * @return
    1454                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1455                 :            :  */
    1456                 :            : int
    1457                 :          0 : mlx5_flow_item_acceptable(const struct rte_eth_dev *dev,
    1458                 :            :                           const struct rte_flow_item *item,
    1459                 :            :                           const uint8_t *mask,
    1460                 :            :                           const uint8_t *nic_mask,
    1461                 :            :                           unsigned int size,
    1462                 :            :                           bool range_accepted,
    1463                 :            :                           struct rte_flow_error *error)
    1464                 :            : {
    1465                 :            :         unsigned int i;
    1466                 :            : 
    1467                 :            :         MLX5_ASSERT(nic_mask);
    1468         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    1469         [ #  # ]:          0 :                 if ((nic_mask[i] | mask[i]) != nic_mask[i])
    1470                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    1471                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    1472                 :            :                                                   item,
    1473                 :            :                                                   "mask enables non supported"
    1474                 :            :                                                   " bits");
    1475         [ #  # ]:          0 :         if (mlx5_hws_active(dev))
    1476                 :            :                 return 0;
    1477   [ #  #  #  #  :          0 :         if (!item->spec && (item->mask || item->last))
                   #  # ]
    1478                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1479                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    1480                 :            :                                           "mask/last without a spec is not"
    1481                 :            :                                           " supported");
    1482   [ #  #  #  #  :          0 :         if (item->spec && item->last && !range_accepted) {
                   #  # ]
    1483                 :          0 :                 uint8_t *spec = alloca(size);
    1484                 :          0 :                 uint8_t *last = alloca(size);
    1485                 :            :                 unsigned int i;
    1486                 :            :                 int ret;
    1487                 :            : 
    1488         [ #  # ]:          0 :                 for (i = 0; i < size; ++i) {
    1489                 :          0 :                         spec[i] = ((const uint8_t *)item->spec)[i] & mask[i];
    1490                 :          0 :                         last[i] = ((const uint8_t *)item->last)[i] & mask[i];
    1491                 :            :                 }
    1492                 :          0 :                 ret = memcmp(spec, last, size);
    1493         [ #  # ]:          0 :                 if (ret != 0)
    1494                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    1495                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    1496                 :            :                                                   item,
    1497                 :            :                                                   "range is not valid");
    1498                 :            :         }
    1499                 :            :         return 0;
    1500                 :            : }
    1501                 :            : 
    1502                 :            : /**
    1503                 :            :  * Adjust the hash fields according to the @p flow information.
    1504                 :            :  *
    1505                 :            :  * @param[in] dev_flow.
    1506                 :            :  *   Pointer to the mlx5_flow.
    1507                 :            :  * @param[in] tunnel
    1508                 :            :  *   1 when the hash field is for a tunnel item.
    1509                 :            :  * @param[in] layer_types
    1510                 :            :  *   RTE_ETH_RSS_* types.
    1511                 :            :  * @param[in] hash_fields
    1512                 :            :  *   Item hash fields.
    1513                 :            :  *
    1514                 :            :  * @return
    1515                 :            :  *   The hash fields that should be used.
    1516                 :            :  */
    1517                 :            : uint64_t
    1518                 :          0 : mlx5_flow_hashfields_adjust(struct mlx5_flow_rss_desc *rss_desc,
    1519                 :            :                             int tunnel __rte_unused, uint64_t layer_types,
    1520                 :            :                             uint64_t hash_fields)
    1521                 :            : {
    1522                 :            : #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
    1523                 :          0 :         int rss_request_inner = rss_desc->level >= 2;
    1524                 :            : 
    1525                 :            :         /* Check RSS hash level for tunnel. */
    1526         [ #  # ]:          0 :         if (tunnel && rss_request_inner)
    1527                 :          0 :                 hash_fields |= IBV_RX_HASH_INNER;
    1528         [ #  # ]:          0 :         else if (tunnel || rss_request_inner)
    1529                 :            :                 return 0;
    1530                 :            : #endif
    1531                 :            :         /* Check if requested layer matches RSS hash fields. */
    1532         [ #  # ]:          0 :         if (!(rss_desc->types & layer_types))
    1533                 :          0 :                 return 0;
    1534                 :            :         return hash_fields;
    1535                 :            : }
    1536                 :            : 
    1537                 :            : /**
    1538                 :            :  * Lookup and set the ptype in the data Rx part.  A single Ptype can be used,
    1539                 :            :  * if several tunnel rules are used on this queue, the tunnel ptype will be
    1540                 :            :  * cleared.
    1541                 :            :  *
    1542                 :            :  * @param rxq_ctrl
    1543                 :            :  *   Rx queue to update.
    1544                 :            :  */
    1545                 :            : static void
    1546                 :            : flow_rxq_tunnel_ptype_update(struct mlx5_rxq_ctrl *rxq_ctrl)
    1547                 :            : {
    1548                 :            :         unsigned int i;
    1549                 :            :         uint32_t tunnel_ptype = 0;
    1550                 :            : 
    1551                 :            :         /* Look up for the ptype to use. */
    1552   [ #  #  #  # ]:          0 :         for (i = 0; i != MLX5_FLOW_TUNNEL; ++i) {
    1553   [ #  #  #  # ]:          0 :                 if (!rxq_ctrl->flow_tunnels_n[i])
    1554                 :          0 :                         continue;
    1555   [ #  #  #  # ]:          0 :                 if (!tunnel_ptype) {
    1556                 :          0 :                         tunnel_ptype = tunnels_info[i].ptype;
    1557                 :            :                 } else {
    1558                 :            :                         tunnel_ptype = 0;
    1559                 :            :                         break;
    1560                 :            :                 }
    1561                 :            :         }
    1562                 :          0 :         rxq_ctrl->rxq.tunnel = tunnel_ptype;
    1563                 :          0 : }
    1564                 :            : 
    1565                 :            : /**
    1566                 :            :  * Set the Rx queue flags (Mark/Flag and Tunnel Ptypes) according to the device
    1567                 :            :  * flow.
    1568                 :            :  *
    1569                 :            :  * @param[in] dev
    1570                 :            :  *   Pointer to the Ethernet device structure.
    1571                 :            :  * @param[in] dev_handle
    1572                 :            :  *   Pointer to device flow handle structure.
    1573                 :            :  */
    1574                 :            : void
    1575                 :          0 : flow_drv_rxq_flags_set(struct rte_eth_dev *dev,
    1576                 :            :                        struct mlx5_flow_handle *dev_handle)
    1577                 :            : {
    1578                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1579                 :          0 :         const int tunnel = !!(dev_handle->layers & MLX5_FLOW_LAYER_TUNNEL);
    1580                 :            :         struct mlx5_ind_table_obj *ind_tbl = NULL;
    1581                 :            :         unsigned int i;
    1582                 :            : 
    1583         [ #  # ]:          0 :         if (dev_handle->fate_action == MLX5_FLOW_FATE_QUEUE) {
    1584                 :            :                 struct mlx5_hrxq *hrxq;
    1585                 :            : 
    1586                 :          0 :                 hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
    1587                 :            :                               dev_handle->rix_hrxq);
    1588         [ #  # ]:          0 :                 if (hrxq)
    1589                 :          0 :                         ind_tbl = hrxq->ind_table;
    1590         [ #  # ]:          0 :         } else if (dev_handle->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
    1591                 :            :                 struct mlx5_shared_action_rss *shared_rss;
    1592                 :            : 
    1593                 :          0 :                 shared_rss = mlx5_ipool_get
    1594                 :          0 :                         (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
    1595                 :            :                          dev_handle->rix_srss);
    1596         [ #  # ]:          0 :                 if (shared_rss)
    1597                 :          0 :                         ind_tbl = shared_rss->ind_tbl;
    1598                 :            :         }
    1599         [ #  # ]:          0 :         if (!ind_tbl)
    1600                 :          0 :                 return;
    1601         [ #  # ]:          0 :         for (i = 0; i != ind_tbl->queues_n; ++i) {
    1602         [ #  # ]:          0 :                 int idx = ind_tbl->queues[i];
    1603                 :            :                 struct mlx5_rxq_ctrl *rxq_ctrl;
    1604                 :            : 
    1605         [ #  # ]:          0 :                 if (mlx5_is_external_rxq(dev, idx))
    1606                 :          0 :                         continue;
    1607                 :          0 :                 rxq_ctrl = mlx5_rxq_ctrl_get(dev, idx);
    1608                 :            :                 MLX5_ASSERT(rxq_ctrl != NULL);
    1609         [ #  # ]:          0 :                 if (rxq_ctrl == NULL)
    1610                 :          0 :                         continue;
    1611                 :            :                 /*
    1612                 :            :                  * To support metadata register copy on Tx loopback,
    1613                 :            :                  * this must be always enabled (metadata may arive
    1614                 :            :                  * from other port - not from local flows only.
    1615                 :            :                  */
    1616         [ #  # ]:          0 :                 if (tunnel) {
    1617                 :            :                         unsigned int j;
    1618                 :            : 
    1619                 :            :                         /* Increase the counter matching the flow. */
    1620         [ #  # ]:          0 :                         for (j = 0; j != MLX5_FLOW_TUNNEL; ++j) {
    1621                 :          0 :                                 if ((tunnels_info[j].tunnel &
    1622         [ #  # ]:          0 :                                      dev_handle->layers) ==
    1623                 :            :                                     tunnels_info[j].tunnel) {
    1624                 :          0 :                                         rxq_ctrl->flow_tunnels_n[j]++;
    1625                 :          0 :                                         break;
    1626                 :            :                                 }
    1627                 :            :                         }
    1628                 :            :                         flow_rxq_tunnel_ptype_update(rxq_ctrl);
    1629                 :            :                 }
    1630                 :            :         }
    1631                 :            : }
    1632                 :            : 
    1633                 :            : static void
    1634                 :          0 : flow_rxq_mark_flag_set(struct rte_eth_dev *dev)
    1635                 :            : {
    1636                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1637                 :            :         struct mlx5_rxq_ctrl *rxq_ctrl;
    1638                 :            :         uint16_t port_id;
    1639                 :            : 
    1640         [ #  # ]:          0 :         if (priv->sh->shared_mark_enabled)
    1641                 :            :                 return;
    1642         [ #  # ]:          0 :         if (priv->master || priv->representor) {
    1643         [ #  # ]:          0 :                 MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
    1644                 :          0 :                         struct mlx5_priv *opriv =
    1645                 :          0 :                                 rte_eth_devices[port_id].data->dev_private;
    1646                 :            : 
    1647         [ #  # ]:          0 :                         if (!opriv ||
    1648         [ #  # ]:          0 :                             opriv->sh != priv->sh ||
    1649   [ #  #  #  # ]:          0 :                             opriv->domain_id != priv->domain_id ||
    1650                 :            :                             opriv->mark_enabled)
    1651                 :          0 :                                 continue;
    1652         [ #  # ]:          0 :                         LIST_FOREACH(rxq_ctrl, &opriv->rxqsctrl, next) {
    1653                 :          0 :                                 rxq_ctrl->rxq.mark = 1;
    1654                 :            :                         }
    1655                 :          0 :                         opriv->mark_enabled = 1;
    1656                 :            :                 }
    1657                 :            :         } else {
    1658         [ #  # ]:          0 :                 LIST_FOREACH(rxq_ctrl, &priv->rxqsctrl, next) {
    1659                 :          0 :                         rxq_ctrl->rxq.mark = 1;
    1660                 :            :                 }
    1661                 :          0 :                 priv->mark_enabled = 1;
    1662                 :            :         }
    1663                 :          0 :         priv->sh->shared_mark_enabled = 1;
    1664                 :            : }
    1665                 :            : 
    1666                 :            : /**
    1667                 :            :  * Set the Rx queue flags (Mark/Flag and Tunnel Ptypes) for a flow
    1668                 :            :  *
    1669                 :            :  * @param[in] dev
    1670                 :            :  *   Pointer to the Ethernet device structure.
    1671                 :            :  * @param[in] flow
    1672                 :            :  *   Pointer to flow structure.
    1673                 :            :  */
    1674                 :            : static void
    1675                 :          0 : flow_rxq_flags_set(struct rte_eth_dev *dev, struct rte_flow *flow)
    1676                 :            : {
    1677                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1678                 :            :         uint32_t handle_idx;
    1679                 :            :         struct mlx5_flow_handle *dev_handle;
    1680                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
    1681                 :            : 
    1682                 :            :         MLX5_ASSERT(wks);
    1683         [ #  # ]:          0 :         if (wks->mark)
    1684                 :          0 :                 flow_rxq_mark_flag_set(dev);
    1685   [ #  #  #  #  :          0 :         SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
                   #  # ]
    1686                 :            :                        handle_idx, dev_handle, next)
    1687                 :          0 :                 flow_drv_rxq_flags_set(dev, dev_handle);
    1688                 :          0 : }
    1689                 :            : 
    1690                 :            : /**
    1691                 :            :  * Clear the Rx queue flags (Mark/Flag and Tunnel Ptype) associated with the
    1692                 :            :  * device flow if no other flow uses it with the same kind of request.
    1693                 :            :  *
    1694                 :            :  * @param dev
    1695                 :            :  *   Pointer to Ethernet device.
    1696                 :            :  * @param[in] dev_handle
    1697                 :            :  *   Pointer to the device flow handle structure.
    1698                 :            :  */
    1699                 :            : static void
    1700                 :          0 : flow_drv_rxq_flags_trim(struct rte_eth_dev *dev,
    1701                 :            :                         struct mlx5_flow_handle *dev_handle)
    1702                 :            : {
    1703                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1704                 :          0 :         const int tunnel = !!(dev_handle->layers & MLX5_FLOW_LAYER_TUNNEL);
    1705                 :            :         struct mlx5_ind_table_obj *ind_tbl = NULL;
    1706                 :            :         unsigned int i;
    1707                 :            : 
    1708         [ #  # ]:          0 :         if (dev_handle->fate_action == MLX5_FLOW_FATE_QUEUE) {
    1709                 :            :                 struct mlx5_hrxq *hrxq;
    1710                 :            : 
    1711                 :          0 :                 hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
    1712                 :            :                               dev_handle->rix_hrxq);
    1713         [ #  # ]:          0 :                 if (hrxq)
    1714                 :          0 :                         ind_tbl = hrxq->ind_table;
    1715         [ #  # ]:          0 :         } else if (dev_handle->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
    1716                 :            :                 struct mlx5_shared_action_rss *shared_rss;
    1717                 :            : 
    1718                 :          0 :                 shared_rss = mlx5_ipool_get
    1719                 :          0 :                         (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
    1720                 :            :                          dev_handle->rix_srss);
    1721         [ #  # ]:          0 :                 if (shared_rss)
    1722                 :          0 :                         ind_tbl = shared_rss->ind_tbl;
    1723                 :            :         }
    1724         [ #  # ]:          0 :         if (!ind_tbl)
    1725                 :          0 :                 return;
    1726                 :            :         MLX5_ASSERT(dev->data->dev_started);
    1727         [ #  # ]:          0 :         for (i = 0; i != ind_tbl->queues_n; ++i) {
    1728         [ #  # ]:          0 :                 int idx = ind_tbl->queues[i];
    1729                 :            :                 struct mlx5_rxq_ctrl *rxq_ctrl;
    1730                 :            : 
    1731         [ #  # ]:          0 :                 if (mlx5_is_external_rxq(dev, idx))
    1732                 :          0 :                         continue;
    1733                 :          0 :                 rxq_ctrl = mlx5_rxq_ctrl_get(dev, idx);
    1734                 :            :                 MLX5_ASSERT(rxq_ctrl != NULL);
    1735         [ #  # ]:          0 :                 if (rxq_ctrl == NULL)
    1736                 :          0 :                         continue;
    1737         [ #  # ]:          0 :                 if (tunnel) {
    1738                 :            :                         unsigned int j;
    1739                 :            : 
    1740                 :            :                         /* Decrease the counter matching the flow. */
    1741         [ #  # ]:          0 :                         for (j = 0; j != MLX5_FLOW_TUNNEL; ++j) {
    1742                 :          0 :                                 if ((tunnels_info[j].tunnel &
    1743         [ #  # ]:          0 :                                      dev_handle->layers) ==
    1744                 :            :                                     tunnels_info[j].tunnel) {
    1745                 :          0 :                                         rxq_ctrl->flow_tunnels_n[j]--;
    1746                 :          0 :                                         break;
    1747                 :            :                                 }
    1748                 :            :                         }
    1749                 :            :                         flow_rxq_tunnel_ptype_update(rxq_ctrl);
    1750                 :            :                 }
    1751                 :            :         }
    1752                 :            : }
    1753                 :            : 
    1754                 :            : /**
    1755                 :            :  * Clear the Rx queue flags (Mark/Flag and Tunnel Ptype) associated with the
    1756                 :            :  * @p flow if no other flow uses it with the same kind of request.
    1757                 :            :  *
    1758                 :            :  * @param dev
    1759                 :            :  *   Pointer to Ethernet device.
    1760                 :            :  * @param[in] flow
    1761                 :            :  *   Pointer to the flow.
    1762                 :            :  */
    1763                 :            : static void
    1764                 :          0 : flow_rxq_flags_trim(struct rte_eth_dev *dev, struct rte_flow *flow)
    1765                 :            : {
    1766                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1767                 :            :         uint32_t handle_idx;
    1768                 :            :         struct mlx5_flow_handle *dev_handle;
    1769                 :            : 
    1770   [ #  #  #  #  :          0 :         SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
                   #  # ]
    1771                 :            :                        handle_idx, dev_handle, next)
    1772                 :          0 :                 flow_drv_rxq_flags_trim(dev, dev_handle);
    1773                 :          0 : }
    1774                 :            : 
    1775                 :            : /**
    1776                 :            :  * Clear the Mark/Flag and Tunnel ptype information in all Rx queues.
    1777                 :            :  *
    1778                 :            :  * @param dev
    1779                 :            :  *   Pointer to Ethernet device.
    1780                 :            :  */
    1781                 :            : static void
    1782                 :          0 : flow_rxq_flags_clear(struct rte_eth_dev *dev)
    1783                 :            : {
    1784                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1785                 :            :         unsigned int i;
    1786                 :            : 
    1787         [ #  # ]:          0 :         for (i = 0; i != priv->rxqs_n; ++i) {
    1788                 :          0 :                 struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, i);
    1789                 :            :                 unsigned int j;
    1790                 :            : 
    1791   [ #  #  #  # ]:          0 :                 if (rxq == NULL || rxq->ctrl == NULL)
    1792                 :          0 :                         continue;
    1793                 :          0 :                 rxq->ctrl->rxq.mark = 0;
    1794         [ #  # ]:          0 :                 for (j = 0; j != MLX5_FLOW_TUNNEL; ++j)
    1795                 :          0 :                         rxq->ctrl->flow_tunnels_n[j] = 0;
    1796                 :          0 :                 rxq->ctrl->rxq.tunnel = 0;
    1797                 :            :         }
    1798                 :          0 :         priv->mark_enabled = 0;
    1799                 :          0 :         priv->sh->shared_mark_enabled = 0;
    1800                 :          0 : }
    1801                 :            : 
    1802                 :            : static uint64_t mlx5_restore_info_dynflag;
    1803                 :            : 
    1804                 :            : int
    1805                 :          0 : mlx5_flow_rx_metadata_negotiate(struct rte_eth_dev *dev, uint64_t *features)
    1806                 :            : {
    1807         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1808                 :            :         uint64_t supported = 0;
    1809                 :            : 
    1810         [ #  # ]:          0 :         if (!is_tunnel_offload_active(dev)) {
    1811                 :            :                 supported |= RTE_ETH_RX_METADATA_USER_FLAG;
    1812                 :            :                 supported |= RTE_ETH_RX_METADATA_USER_MARK;
    1813         [ #  # ]:          0 :                 if ((*features & RTE_ETH_RX_METADATA_TUNNEL_ID) != 0) {
    1814                 :          0 :                         DRV_LOG(DEBUG,
    1815                 :            :                                 "tunnel offload was not activated, consider setting dv_xmeta_en=%d",
    1816                 :            :                                 MLX5_XMETA_MODE_MISS_INFO);
    1817                 :            :                 }
    1818                 :            :         } else {
    1819                 :            :                 supported |= RTE_ETH_RX_METADATA_TUNNEL_ID;
    1820         [ #  # ]:          0 :                 if ((*features & RTE_ETH_RX_METADATA_TUNNEL_ID) != 0 &&
    1821         [ #  # ]:          0 :                                 mlx5_restore_info_dynflag == 0)
    1822                 :          0 :                         mlx5_restore_info_dynflag = rte_flow_restore_info_dynflag();
    1823                 :            :         }
    1824                 :            : 
    1825         [ #  # ]:          0 :         if (((*features & supported) & RTE_ETH_RX_METADATA_TUNNEL_ID) != 0)
    1826                 :          0 :                 priv->tunnel_enabled = 1;
    1827                 :            :         else
    1828                 :          0 :                 priv->tunnel_enabled = 0;
    1829                 :            : 
    1830                 :          0 :         *features &= supported;
    1831                 :          0 :         return 0;
    1832                 :            : }
    1833                 :            : 
    1834                 :            : /**
    1835                 :            :  * Set the Rx queue dynamic metadata (mask and offset) for a flow
    1836                 :            :  *
    1837                 :            :  * @param[in] dev
    1838                 :            :  *   Pointer to the Ethernet device structure.
    1839                 :            :  */
    1840                 :            : void
    1841                 :          0 : mlx5_flow_rxq_dynf_set(struct rte_eth_dev *dev)
    1842                 :            : {
    1843                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1844                 :            :         uint64_t mark_flag = RTE_MBUF_F_RX_FDIR_ID;
    1845                 :            :         unsigned int i;
    1846                 :            : 
    1847         [ #  # ]:          0 :         if (priv->tunnel_enabled)
    1848                 :          0 :                 mark_flag |= mlx5_restore_info_dynflag;
    1849                 :            : 
    1850         [ #  # ]:          0 :         for (i = 0; i != priv->rxqs_n; ++i) {
    1851                 :          0 :                 struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, i);
    1852                 :            :                 struct mlx5_rxq_data *data;
    1853                 :            : 
    1854   [ #  #  #  # ]:          0 :                 if (rxq == NULL || rxq->ctrl == NULL)
    1855                 :          0 :                         continue;
    1856                 :            :                 data = &rxq->ctrl->rxq;
    1857   [ #  #  #  # ]:          0 :                 if (!data->shared || !rxq->ctrl->started) {
    1858         [ #  # ]:          0 :                         if (!rte_flow_dynf_metadata_avail()) {
    1859                 :          0 :                                 data->dynf_meta = 0;
    1860                 :          0 :                                 data->flow_meta_mask = 0;
    1861                 :          0 :                                 data->flow_meta_offset = -1;
    1862                 :          0 :                                 data->flow_meta_port_mask = 0;
    1863                 :            :                         } else {
    1864                 :          0 :                                 data->dynf_meta = 1;
    1865                 :          0 :                                 data->flow_meta_mask = rte_flow_dynf_metadata_mask;
    1866                 :          0 :                                 data->flow_meta_offset = rte_flow_dynf_metadata_offs;
    1867                 :          0 :                                 data->flow_meta_port_mask = priv->sh->dv_meta_mask;
    1868                 :            :                         }
    1869                 :          0 :                         data->mark_flag = mark_flag;
    1870                 :            :                 }
    1871                 :            :         }
    1872                 :          0 : }
    1873                 :            : 
    1874                 :            : /*
    1875                 :            :  * return a pointer to the desired action in the list of actions.
    1876                 :            :  *
    1877                 :            :  * @param[in] actions
    1878                 :            :  *   The list of actions to search the action in.
    1879                 :            :  * @param[in] action
    1880                 :            :  *   The action to find.
    1881                 :            :  *
    1882                 :            :  * @return
    1883                 :            :  *   Pointer to the action in the list, if found. NULL otherwise.
    1884                 :            :  */
    1885                 :            : const struct rte_flow_action *
    1886                 :          0 : mlx5_flow_find_action(const struct rte_flow_action *actions,
    1887                 :            :                       enum rte_flow_action_type action)
    1888                 :            : {
    1889         [ #  # ]:          0 :         if (actions == NULL)
    1890                 :            :                 return NULL;
    1891         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
    1892         [ #  # ]:          0 :                 if (actions->type == action)
    1893                 :          0 :                         return actions;
    1894                 :            :         return NULL;
    1895                 :            : }
    1896                 :            : 
    1897                 :            : /*
    1898                 :            :  * Validate the flag action.
    1899                 :            :  *
    1900                 :            :  * @param[in] action_flags
    1901                 :            :  *   Bit-fields that holds the actions detected until now.
    1902                 :            :  * @param[in] attr
    1903                 :            :  *   Attributes of flow that includes this action.
    1904                 :            :  * @param[out] error
    1905                 :            :  *   Pointer to error structure.
    1906                 :            :  *
    1907                 :            :  * @return
    1908                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1909                 :            :  */
    1910                 :            : int
    1911                 :          0 : mlx5_flow_validate_action_flag(uint64_t action_flags,
    1912                 :            :                                const struct rte_flow_attr *attr,
    1913                 :            :                                struct rte_flow_error *error)
    1914                 :            : {
    1915         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_MARK)
    1916                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1917                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1918                 :            :                                           "can't mark and flag in same flow");
    1919         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_FLAG)
    1920                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1921                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1922                 :            :                                           "can't have 2 flag"
    1923                 :            :                                           " actions in same flow");
    1924         [ #  # ]:          0 :         if (attr->egress)
    1925                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    1926                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
    1927                 :            :                                           "flag action not supported for "
    1928                 :            :                                           "egress");
    1929                 :            :         return 0;
    1930                 :            : }
    1931                 :            : 
    1932                 :            : /*
    1933                 :            :  * Validate the mark action.
    1934                 :            :  *
    1935                 :            :  * @param[in] action
    1936                 :            :  *   Pointer to the queue action.
    1937                 :            :  * @param[in] action_flags
    1938                 :            :  *   Bit-fields that holds the actions detected until now.
    1939                 :            :  * @param[in] attr
    1940                 :            :  *   Attributes of flow that includes this action.
    1941                 :            :  * @param[out] error
    1942                 :            :  *   Pointer to error structure.
    1943                 :            :  *
    1944                 :            :  * @return
    1945                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1946                 :            :  */
    1947                 :            : int
    1948                 :          0 : mlx5_flow_validate_action_mark(__rte_unused struct rte_eth_dev *dev,
    1949                 :            :                                const struct rte_flow_action *action,
    1950                 :            :                                uint64_t action_flags,
    1951                 :            :                                const struct rte_flow_attr *attr,
    1952                 :            :                                struct rte_flow_error *error)
    1953                 :            : {
    1954                 :          0 :         const struct rte_flow_action_mark *mark = action->conf;
    1955                 :            : 
    1956         [ #  # ]:          0 :         if (!mark)
    1957                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1958                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    1959                 :            :                                           action,
    1960                 :            :                                           "configuration cannot be null");
    1961         [ #  # ]:          0 :         if (mark->id >= MLX5_FLOW_MARK_MAX)
    1962                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1963                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    1964                 :          0 :                                           &mark->id,
    1965                 :            :                                           "mark id must in 0 <= id < "
    1966                 :            :                                           RTE_STR(MLX5_FLOW_MARK_MAX));
    1967         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_FLAG)
    1968                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1969                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1970                 :            :                                           "can't flag and mark in same flow");
    1971         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_MARK)
    1972                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1973                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1974                 :            :                                           "can't have 2 mark actions in same"
    1975                 :            :                                           " flow");
    1976         [ #  # ]:          0 :         if (attr->egress)
    1977                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    1978                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
    1979                 :            :                                           "mark action not supported for "
    1980                 :            :                                           "egress");
    1981                 :            :         return 0;
    1982                 :            : }
    1983                 :            : 
    1984                 :            : /*
    1985                 :            :  * Validate the drop action.
    1986                 :            :  *
    1987                 :            :  * @param[in] dev
    1988                 :            :  *   Pointer to the Ethernet device structure.
    1989                 :            :  * @param[in] is_root
    1990                 :            :  *   True if flow is validated for root table. False otherwise.
    1991                 :            :  * @param[in] attr
    1992                 :            :  *   Attributes of flow that includes this action.
    1993                 :            :  * @param[out] error
    1994                 :            :  *   Pointer to error structure.
    1995                 :            :  *
    1996                 :            :  * @return
    1997                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1998                 :            :  */
    1999                 :            : int
    2000                 :          0 : mlx5_flow_validate_action_drop(struct rte_eth_dev *dev,
    2001                 :            :                                bool is_root,
    2002                 :            :                                const struct rte_flow_attr *attr,
    2003                 :            :                                struct rte_flow_error *error)
    2004                 :            : {
    2005                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2006                 :            : 
    2007   [ #  #  #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 0 && attr->egress)
    2008                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2009                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
    2010                 :            :                                           "drop action not supported for "
    2011                 :            :                                           "egress");
    2012   [ #  #  #  #  :          0 :         if (priv->sh->config.dv_flow_en == 1 && is_root && (attr->egress || attr->transfer) &&
                   #  # ]
    2013         [ #  # ]:          0 :             !priv->sh->dr_root_drop_action_en) {
    2014                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2015                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    2016                 :            :                                           "drop action not supported for "
    2017                 :            :                                           "egress and transfer on group 0");
    2018                 :            :         }
    2019                 :            :         return 0;
    2020                 :            : }
    2021                 :            : 
    2022                 :            : /*
    2023                 :            :  * Check if a queue specified in the queue action is valid.
    2024                 :            :  *
    2025                 :            :  * @param[in] dev
    2026                 :            :  *   Pointer to the Ethernet device structure.
    2027                 :            :  * @param[in] action
    2028                 :            :  *   Pointer to the queue action.
    2029                 :            :  * @param[out] error
    2030                 :            :  *   Pointer to error structure.
    2031                 :            :  *
    2032                 :            :  * @return
    2033                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2034                 :            :  */
    2035                 :            : int
    2036                 :          0 : mlx5_flow_validate_target_queue(struct rte_eth_dev *dev,
    2037                 :            :                                 const struct rte_flow_action *action,
    2038                 :            :                                 struct rte_flow_error *error)
    2039                 :            : {
    2040                 :          0 :         const struct rte_flow_action_queue *queue = action->conf;
    2041                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2042                 :            : 
    2043   [ #  #  #  # ]:          0 :         if (mlx5_is_external_rxq(dev, queue->index))
    2044                 :            :                 return 0;
    2045         [ #  # ]:          0 :         if (!priv->rxqs_n)
    2046                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2047                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2048                 :            :                                           NULL, "No Rx queues configured");
    2049         [ #  # ]:          0 :         if (queue->index >= priv->rxqs_n)
    2050                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2051                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2052                 :          0 :                                           &queue->index,
    2053                 :            :                                           "queue index out of range");
    2054         [ #  # ]:          0 :         if (mlx5_rxq_get(dev, queue->index) == NULL)
    2055                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2056                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2057                 :          0 :                                           &queue->index,
    2058                 :            :                                           "queue is not configured");
    2059                 :            :         return 0;
    2060                 :            : }
    2061                 :            : 
    2062                 :            : /*
    2063                 :            :  * Validate the queue action.
    2064                 :            :  *
    2065                 :            :  * @param[in] action
    2066                 :            :  *   Pointer to the queue action.
    2067                 :            :  * @param[in] action_flags
    2068                 :            :  *   Bit-fields that holds the actions detected until now.
    2069                 :            :  * @param[in] dev
    2070                 :            :  *   Pointer to the Ethernet device structure.
    2071                 :            :  * @param[in] attr
    2072                 :            :  *   Attributes of flow that includes this action.
    2073                 :            :  * @param[out] error
    2074                 :            :  *   Pointer to error structure.
    2075                 :            :  *
    2076                 :            :  * @return
    2077                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2078                 :            :  */
    2079                 :            : int
    2080                 :          0 : mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
    2081                 :            :                                 uint64_t action_flags,
    2082                 :            :                                 struct rte_eth_dev *dev,
    2083                 :            :                                 const struct rte_flow_attr *attr,
    2084                 :            :                                 struct rte_flow_error *error)
    2085                 :            : {
    2086                 :          0 :         const struct rte_flow_action_queue *queue = action->conf;
    2087                 :            : 
    2088         [ #  # ]:          0 :         if (!queue)
    2089                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2090                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    2091                 :            :                                           "no QUEUE action configuration");
    2092         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_FATE_ACTIONS)
    2093                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2094                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    2095                 :            :                                           "can't have 2 fate actions in"
    2096                 :            :                                           " same flow");
    2097         [ #  # ]:          0 :         if (attr->egress)
    2098                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2099                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
    2100                 :            :                                           "queue action not supported for egress.");
    2101                 :          0 :         return mlx5_flow_validate_target_queue(dev, action, error);
    2102                 :            : }
    2103                 :            : 
    2104                 :            : /**
    2105                 :            :  * Validate queue numbers for device RSS.
    2106                 :            :  *
    2107                 :            :  * @param[in] dev
    2108                 :            :  *   Configured device.
    2109                 :            :  * @param[in] queues
    2110                 :            :  *   Array of queue numbers.
    2111                 :            :  * @param[in] queues_n
    2112                 :            :  *   Size of the @p queues array.
    2113                 :            :  * @param[out] error
    2114                 :            :  *   On error, filled with a textual error description.
    2115                 :            :  * @param[out] queue_idx
    2116                 :            :  *   On error, filled with an offending queue index in @p queues array.
    2117                 :            :  *
    2118                 :            :  * @return
    2119                 :            :  *   0 on success, a negative errno code on error.
    2120                 :            :  */
    2121                 :            : static int
    2122                 :          0 : mlx5_validate_rss_queues(struct rte_eth_dev *dev,
    2123                 :            :                          const uint16_t *queues, uint32_t queues_n,
    2124                 :            :                          const char **error, uint32_t *queue_idx)
    2125                 :            : {
    2126                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    2127                 :            :         bool is_hairpin = false;
    2128                 :            :         bool is_ext_rss = false;
    2129                 :            :         uint32_t i;
    2130                 :            : 
    2131         [ #  # ]:          0 :         for (i = 0; i != queues_n; ++i) {
    2132                 :            :                 struct mlx5_rxq_ctrl *rxq_ctrl;
    2133                 :            : 
    2134   [ #  #  #  # ]:          0 :                 if (mlx5_is_external_rxq(dev, queues[0])) {
    2135                 :            :                         is_ext_rss = true;
    2136                 :          0 :                         continue;
    2137                 :            :                 }
    2138         [ #  # ]:          0 :                 if (is_ext_rss) {
    2139                 :          0 :                         *error = "Combining external and regular RSS queues is not supported";
    2140                 :          0 :                         *queue_idx = i;
    2141                 :          0 :                         return -ENOTSUP;
    2142                 :            :                 }
    2143         [ #  # ]:          0 :                 if (queues[i] >= priv->rxqs_n) {
    2144                 :          0 :                         *error = "queue index out of range";
    2145                 :          0 :                         *queue_idx = i;
    2146                 :          0 :                         return -EINVAL;
    2147                 :            :                 }
    2148                 :          0 :                 rxq_ctrl = mlx5_rxq_ctrl_get(dev, queues[i]);
    2149         [ #  # ]:          0 :                 if (rxq_ctrl == NULL) {
    2150                 :          0 :                         *error =  "queue is not configured";
    2151                 :          0 :                         *queue_idx = i;
    2152                 :          0 :                         return -EINVAL;
    2153                 :            :                 }
    2154   [ #  #  #  # ]:          0 :                 if (i == 0 && rxq_ctrl->is_hairpin)
    2155                 :            :                         is_hairpin = true;
    2156         [ #  # ]:          0 :                 if (is_hairpin != rxq_ctrl->is_hairpin) {
    2157                 :          0 :                         *error = "combining hairpin and regular RSS queues is not supported";
    2158                 :          0 :                         *queue_idx = i;
    2159                 :          0 :                         return -ENOTSUP;
    2160                 :            :                 }
    2161                 :            :         }
    2162                 :            :         return 0;
    2163                 :            : }
    2164                 :            : 
    2165                 :            : /*
    2166                 :            :  * Validate the rss action.
    2167                 :            :  *
    2168                 :            :  * @param[in] dev
    2169                 :            :  *   Pointer to the Ethernet device structure.
    2170                 :            :  * @param[in] action
    2171                 :            :  *   Pointer to the queue action.
    2172                 :            :  * @param[out] error
    2173                 :            :  *   Pointer to error structure.
    2174                 :            :  *
    2175                 :            :  * @return
    2176                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2177                 :            :  */
    2178                 :            : int
    2179                 :          0 : mlx5_validate_action_rss(struct rte_eth_dev *dev,
    2180                 :            :                          const struct rte_flow_action *action,
    2181                 :            :                          struct rte_flow_error *error)
    2182                 :            : {
    2183                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2184                 :          0 :         const struct rte_flow_action_rss *rss = action->conf;
    2185                 :            :         int ret;
    2186                 :            :         const char *message;
    2187                 :            :         uint32_t queue_idx;
    2188                 :            : 
    2189         [ #  # ]:          0 :         if (!rss)
    2190                 :          0 :                 return rte_flow_error_set
    2191                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
    2192                 :            :                          action, "no RSS action configuration");
    2193         [ #  # ]:          0 :         if (rss->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) {
    2194                 :          0 :                 DRV_LOG(WARNING, "port %u symmetric RSS supported with SORT",
    2195                 :            :                         dev->data->port_id);
    2196         [ #  # ]:          0 :         } else if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT &&
    2197                 :            :                    rss->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ)
    2198                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2199                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2200                 :          0 :                                           &rss->func,
    2201                 :            :                                           "RSS hash function not supported");
    2202                 :            : #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
    2203         [ #  # ]:          0 :         if (rss->level > 2)
    2204                 :            : #else
    2205                 :            :         if (rss->level > 1)
    2206                 :            : #endif
    2207                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2208                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2209                 :          0 :                                           &rss->level,
    2210                 :            :                                           "tunnel RSS is not supported");
    2211                 :            :         /* allow RSS key_len 0 in case of NULL (default) RSS key. */
    2212   [ #  #  #  # ]:          0 :         if (rss->key_len == 0 && rss->key != NULL)
    2213                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2214                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2215                 :          0 :                                           &rss->key_len,
    2216                 :            :                                           "RSS hash key length 0");
    2217         [ #  # ]:          0 :         if (rss->key_len > 0 && rss->key_len < MLX5_RSS_HASH_KEY_LEN)
    2218                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2219                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2220                 :          0 :                                           &rss->key_len,
    2221                 :            :                                           "RSS hash key too small");
    2222         [ #  # ]:          0 :         if (rss->key_len > MLX5_RSS_HASH_KEY_LEN)
    2223                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2224                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2225                 :          0 :                                           &rss->key_len,
    2226                 :            :                                           "RSS hash key too large");
    2227         [ #  # ]:          0 :         if (rss->queue_num > priv->sh->dev_cap.ind_table_max_size)
    2228                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2229                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2230                 :          0 :                                           &rss->queue_num,
    2231                 :            :                                           "number of queues too large");
    2232         [ #  # ]:          0 :         if (rss->types & MLX5_RSS_HF_MASK)
    2233                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2234                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2235                 :          0 :                                           &rss->types,
    2236                 :            :                                           "some RSS protocols are not"
    2237                 :            :                                           " supported");
    2238         [ #  # ]:          0 :         if ((rss->types & (RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY)) &&
    2239         [ #  # ]:          0 :             !(rss->types & RTE_ETH_RSS_IP))
    2240                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2241                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    2242                 :            :                                           "L3 partial RSS requested but L3 RSS"
    2243                 :            :                                           " type not specified");
    2244         [ #  # ]:          0 :         if ((rss->types & (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY)) &&
    2245         [ #  # ]:          0 :             !(rss->types & (RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP)))
    2246                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2247                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    2248                 :            :                                           "L4 partial RSS requested but L4 RSS"
    2249                 :            :                                           " type not specified");
    2250   [ #  #  #  # ]:          0 :         if (!priv->rxqs_n && priv->ext_rxqs == NULL)
    2251                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2252                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2253                 :            :                                           NULL, "No Rx queues configured");
    2254         [ #  # ]:          0 :         if (!rss->queue_num)
    2255                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2256                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2257                 :            :                                           NULL, "No queues configured");
    2258                 :          0 :         ret = mlx5_validate_rss_queues(dev, rss->queue, rss->queue_num,
    2259                 :            :                                        &message, &queue_idx);
    2260         [ #  # ]:          0 :         if (ret != 0) {
    2261                 :          0 :                 return rte_flow_error_set(error, -ret,
    2262                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2263                 :          0 :                                           &rss->queue[queue_idx], message);
    2264                 :            :         }
    2265                 :            :         return 0;
    2266                 :            : }
    2267                 :            : 
    2268                 :            : /*
    2269                 :            :  * Validate the rss action.
    2270                 :            :  *
    2271                 :            :  * @param[in] action
    2272                 :            :  *   Pointer to the queue action.
    2273                 :            :  * @param[in] action_flags
    2274                 :            :  *   Bit-fields that holds the actions detected until now.
    2275                 :            :  * @param[in] dev
    2276                 :            :  *   Pointer to the Ethernet device structure.
    2277                 :            :  * @param[in] attr
    2278                 :            :  *   Attributes of flow that includes this action.
    2279                 :            :  * @param[in] item_flags
    2280                 :            :  *   Items that were detected.
    2281                 :            :  * @param[out] error
    2282                 :            :  *   Pointer to error structure.
    2283                 :            :  *
    2284                 :            :  * @return
    2285                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2286                 :            :  */
    2287                 :            : int
    2288                 :          0 : mlx5_flow_validate_action_rss(const struct rte_flow_action *action,
    2289                 :            :                               uint64_t action_flags,
    2290                 :            :                               struct rte_eth_dev *dev,
    2291                 :            :                               const struct rte_flow_attr *attr,
    2292                 :            :                               uint64_t item_flags,
    2293                 :            :                               struct rte_flow_error *error)
    2294                 :            : {
    2295                 :          0 :         const struct rte_flow_action_rss *rss = action->conf;
    2296                 :          0 :         int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2297                 :            :         int ret;
    2298                 :            : 
    2299         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_FATE_ACTIONS)
    2300                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2301                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    2302                 :            :                                           "can't have 2 fate actions"
    2303                 :            :                                           " in same flow");
    2304                 :          0 :         ret = mlx5_validate_action_rss(dev, action, error);
    2305         [ #  # ]:          0 :         if (ret)
    2306                 :            :                 return ret;
    2307         [ #  # ]:          0 :         if (attr->egress)
    2308                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2309                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
    2310                 :            :                                           "rss action not supported for "
    2311                 :            :                                           "egress");
    2312   [ #  #  #  # ]:          0 :         if (rss->level > 1 && !tunnel)
    2313                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2314                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    2315                 :            :                                           "inner RSS is not supported for "
    2316                 :            :                                           "non-tunnel flows");
    2317         [ #  # ]:          0 :         if ((item_flags & MLX5_FLOW_LAYER_ECPRI) &&
    2318                 :            :             !(item_flags & MLX5_FLOW_LAYER_INNER_L4_UDP)) {
    2319                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2320                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    2321                 :            :                                           "RSS on eCPRI is not supported now");
    2322                 :            :         }
    2323         [ #  # ]:          0 :         if ((item_flags & MLX5_FLOW_LAYER_MPLS) &&
    2324                 :            :             !(item_flags &
    2325         [ #  # ]:          0 :               (MLX5_FLOW_LAYER_INNER_L2 | MLX5_FLOW_LAYER_INNER_L3)) &&
    2326                 :            :             rss->level > 1)
    2327                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2328                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    2329                 :            :                                           "MPLS inner RSS needs to specify inner L2/L3 items after MPLS in pattern");
    2330                 :            :         return 0;
    2331                 :            : }
    2332                 :            : 
    2333                 :            : /*
    2334                 :            :  * Validate the default miss action.
    2335                 :            :  *
    2336                 :            :  * @param[in] action_flags
    2337                 :            :  *   Bit-fields that holds the actions detected until now.
    2338                 :            :  * @param[out] error
    2339                 :            :  *   Pointer to error structure.
    2340                 :            :  *
    2341                 :            :  * @return
    2342                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2343                 :            :  */
    2344                 :            : int
    2345                 :          0 : mlx5_flow_validate_action_default_miss(uint64_t action_flags,
    2346                 :            :                                 const struct rte_flow_attr *attr,
    2347                 :            :                                 struct rte_flow_error *error)
    2348                 :            : {
    2349         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_FATE_ACTIONS)
    2350                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2351                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    2352                 :            :                                           "can't have 2 fate actions in"
    2353                 :            :                                           " same flow");
    2354         [ #  # ]:          0 :         if (attr->egress)
    2355                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2356                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
    2357                 :            :                                           "default miss action not supported "
    2358                 :            :                                           "for egress");
    2359         [ #  # ]:          0 :         if (attr->group)
    2360                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2361                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
    2362                 :            :                                           "only group 0 is supported");
    2363         [ #  # ]:          0 :         if (attr->transfer)
    2364                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2365                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
    2366                 :            :                                           NULL, "transfer is not supported");
    2367                 :            :         return 0;
    2368                 :            : }
    2369                 :            : 
    2370                 :            : /*
    2371                 :            :  * Validate the count action.
    2372                 :            :  *
    2373                 :            :  * @param[in] dev
    2374                 :            :  *   Pointer to the Ethernet device structure.
    2375                 :            :  * @param[in] attr
    2376                 :            :  *   Attributes of flow that includes this action.
    2377                 :            :  * @param[out] error
    2378                 :            :  *   Pointer to error structure.
    2379                 :            :  *
    2380                 :            :  * @return
    2381                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2382                 :            :  */
    2383                 :            : int
    2384                 :          0 : mlx5_flow_validate_action_count(struct rte_eth_dev *dev __rte_unused,
    2385                 :            :                                 const struct rte_flow_attr *attr,
    2386                 :            :                                 struct rte_flow_error *error)
    2387                 :            : {
    2388         [ #  # ]:          0 :         if (attr->egress)
    2389                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2390                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
    2391                 :            :                                           "count action not supported for "
    2392                 :            :                                           "egress");
    2393                 :            :         return 0;
    2394                 :            : }
    2395                 :            : 
    2396                 :            : /*
    2397                 :            :  * Validate the ASO CT action.
    2398                 :            :  *
    2399                 :            :  * @param[in] dev
    2400                 :            :  *   Pointer to the Ethernet device structure.
    2401                 :            :  * @param[in] conntrack
    2402                 :            :  *   Pointer to the CT action profile.
    2403                 :            :  * @param[out] error
    2404                 :            :  *   Pointer to error structure.
    2405                 :            :  *
    2406                 :            :  * @return
    2407                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2408                 :            :  */
    2409                 :            : int
    2410                 :          0 : mlx5_validate_action_ct(struct rte_eth_dev *dev,
    2411                 :            :                         const struct rte_flow_action_conntrack *conntrack,
    2412                 :            :                         struct rte_flow_error *error)
    2413                 :            : {
    2414                 :            :         RTE_SET_USED(dev);
    2415                 :            : 
    2416         [ #  # ]:          0 :         if (conntrack->state > RTE_FLOW_CONNTRACK_STATE_TIME_WAIT)
    2417                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2418                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    2419                 :            :                                           "Invalid CT state");
    2420         [ #  # ]:          0 :         if (conntrack->last_index > RTE_FLOW_CONNTRACK_FLAG_RST)
    2421                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2422                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    2423                 :            :                                           "Invalid last TCP packet flag");
    2424                 :            :         return 0;
    2425                 :            : }
    2426                 :            : 
    2427                 :            : /**
    2428                 :            :  * Validate the level value for modify field action.
    2429                 :            :  *
    2430                 :            :  * @param[in] data
    2431                 :            :  *   Pointer to the rte_flow_field_data structure either src or dst.
    2432                 :            :  * @param[out] error
    2433                 :            :  *   Pointer to error structure.
    2434                 :            :  *
    2435                 :            :  * @return
    2436                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2437                 :            :  */
    2438                 :            : int
    2439                 :          0 : flow_validate_modify_field_level(const struct rte_flow_field_data *data,
    2440                 :            :                                  struct rte_flow_error *error)
    2441                 :            : {
    2442   [ #  #  #  # ]:          0 :         if (data->level == 0 || data->field == RTE_FLOW_FIELD_FLEX_ITEM)
    2443                 :            :                 return 0;
    2444         [ #  # ]:          0 :         if (data->field != RTE_FLOW_FIELD_TAG &&
    2445                 :            :             data->field != (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG) {
    2446         [ #  # ]:          0 :                 if (data->level > 1)
    2447                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2448                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    2449                 :            :                                                   NULL,
    2450                 :            :                                                   "inner header fields modification is not supported");
    2451                 :            :                 return 0;
    2452                 :            :         }
    2453         [ #  # ]:          0 :         if (data->tag_index != 0)
    2454                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2455                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    2456                 :            :                                           "tag array can be provided using 'level' or 'tag_index' fields, not both");
    2457                 :            :         /*
    2458                 :            :          * The tag array for RTE_FLOW_FIELD_TAG type is provided using
    2459                 :            :          * 'tag_index' field. In old API, it was provided using 'level' field
    2460                 :            :          * and it is still supported for backwards compatibility.
    2461                 :            :          */
    2462                 :          0 :         DRV_LOG(DEBUG, "tag array provided in 'level' field instead of 'tag_index' field.");
    2463                 :          0 :         return 0;
    2464                 :            : }
    2465                 :            : 
    2466                 :            : /**
    2467                 :            :  * Validate ICMP6 item.
    2468                 :            :  *
    2469                 :            :  * @param[in] item
    2470                 :            :  *   Item specification.
    2471                 :            :  * @param[in] item_flags
    2472                 :            :  *   Bit-fields that holds the items detected until now.
    2473                 :            :  * @param[in] ext_vlan_sup
    2474                 :            :  *   Whether extended VLAN features are supported or not.
    2475                 :            :  * @param[out] error
    2476                 :            :  *   Pointer to error structure.
    2477                 :            :  *
    2478                 :            :  * @return
    2479                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2480                 :            :  */
    2481                 :            : int
    2482                 :          0 : mlx5_flow_validate_item_icmp6(const struct rte_eth_dev *dev,
    2483                 :            :                               const struct rte_flow_item *item,
    2484                 :            :                               uint64_t item_flags,
    2485                 :            :                               uint8_t target_protocol,
    2486                 :            :                               struct rte_flow_error *error)
    2487                 :            : {
    2488                 :          0 :         const struct rte_flow_item_icmp6 *mask = item->mask;
    2489                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2490         [ #  # ]:          0 :         const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    2491                 :            :                                       MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    2492         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    2493                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    2494                 :            :         int ret;
    2495                 :            : 
    2496         [ #  # ]:          0 :         if (target_protocol != 0xFF && target_protocol != IPPROTO_ICMPV6)
    2497                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2498                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2499                 :            :                                           "protocol filtering not compatible"
    2500                 :            :                                           " with ICMP6 layer");
    2501         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    2502         [ #  # ]:          0 :                 if (!(item_flags & l3m))
    2503                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2504                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2505                 :            :                                                   item, "IPv6 is mandatory to filter on ICMP6");
    2506                 :            :         }
    2507         [ #  # ]:          0 :         if (item_flags & l4m)
    2508                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2509                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2510                 :            :                                           "multiple L4 layers not supported");
    2511         [ #  # ]:          0 :         if (!mask)
    2512                 :            :                 mask = &rte_flow_item_icmp6_mask;
    2513                 :          0 :         ret = mlx5_flow_item_acceptable
    2514                 :            :                 (dev, item, (const uint8_t *)mask,
    2515                 :            :                  (const uint8_t *)&rte_flow_item_icmp6_mask,
    2516                 :            :                  sizeof(struct rte_flow_item_icmp6),
    2517                 :            :                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2518                 :            :         if (ret < 0)
    2519                 :            :                 return ret;
    2520                 :            :         return 0;
    2521                 :            : }
    2522                 :            : 
    2523                 :            : /**
    2524                 :            :  * Validate ICMP6 echo request/reply item.
    2525                 :            :  *
    2526                 :            :  * @param[in] item
    2527                 :            :  *   Item specification.
    2528                 :            :  * @param[in] item_flags
    2529                 :            :  *   Bit-fields that holds the items detected until now.
    2530                 :            :  * @param[in] ext_vlan_sup
    2531                 :            :  *   Whether extended VLAN features are supported or not.
    2532                 :            :  * @param[out] error
    2533                 :            :  *   Pointer to error structure.
    2534                 :            :  *
    2535                 :            :  * @return
    2536                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2537                 :            :  */
    2538                 :            : int
    2539                 :          0 : mlx5_flow_validate_item_icmp6_echo(const struct rte_eth_dev *dev,
    2540                 :            :                                    const struct rte_flow_item *item,
    2541                 :            :                                    uint64_t item_flags,
    2542                 :            :                                    uint8_t target_protocol,
    2543                 :            :                                    struct rte_flow_error *error)
    2544                 :            : {
    2545                 :          0 :         const struct rte_flow_item_icmp6_echo *mask = item->mask;
    2546                 :          0 :         const struct rte_flow_item_icmp6_echo nic_mask = {
    2547                 :            :                 .hdr.base.type = 0xff,
    2548                 :            :                 .hdr.base.code = 0xff,
    2549                 :            :                 .hdr.identifier = RTE_BE16(0xffff),
    2550                 :            :                 .hdr.sequence = RTE_BE16(0xffff),
    2551                 :            :         };
    2552                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2553         [ #  # ]:          0 :         const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    2554                 :            :                                       MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    2555         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    2556                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    2557                 :            :         int ret;
    2558                 :            : 
    2559         [ #  # ]:          0 :         if (target_protocol != 0xFF && target_protocol != IPPROTO_ICMPV6)
    2560                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2561                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2562                 :            :                                           "protocol filtering not compatible"
    2563                 :            :                                           " with ICMP6 layer");
    2564         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    2565         [ #  # ]:          0 :                 if (!(item_flags & l3m))
    2566                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2567                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2568                 :            :                                                   item, "IPv6 is mandatory to filter on ICMP6");
    2569                 :            :         }
    2570         [ #  # ]:          0 :         if (item_flags & l4m)
    2571                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2572                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2573                 :            :                                           "multiple L4 layers not supported");
    2574         [ #  # ]:          0 :         if (!mask)
    2575                 :            :                 mask = &nic_mask;
    2576                 :          0 :         ret = mlx5_flow_item_acceptable
    2577                 :            :                 (dev, item, (const uint8_t *)mask,
    2578                 :            :                  (const uint8_t *)&nic_mask,
    2579                 :            :                  sizeof(struct rte_flow_item_icmp6_echo),
    2580                 :            :                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2581                 :            :         if (ret < 0)
    2582                 :            :                 return ret;
    2583                 :            :         return 0;
    2584                 :            : }
    2585                 :            : 
    2586                 :            : /**
    2587                 :            :  * Validate ICMP item.
    2588                 :            :  *
    2589                 :            :  * @param[in] item
    2590                 :            :  *   Item specification.
    2591                 :            :  * @param[in] item_flags
    2592                 :            :  *   Bit-fields that holds the items detected until now.
    2593                 :            :  * @param[out] error
    2594                 :            :  *   Pointer to error structure.
    2595                 :            :  *
    2596                 :            :  * @return
    2597                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2598                 :            :  */
    2599                 :            : int
    2600                 :          0 : mlx5_flow_validate_item_icmp(const struct rte_eth_dev *dev,
    2601                 :            :                              const struct rte_flow_item *item,
    2602                 :            :                              uint64_t item_flags,
    2603                 :            :                              uint8_t target_protocol,
    2604                 :            :                              struct rte_flow_error *error)
    2605                 :            : {
    2606                 :          0 :         const struct rte_flow_item_icmp *mask = item->mask;
    2607                 :          0 :         const struct rte_flow_item_icmp nic_mask = {
    2608                 :            :                 .hdr.icmp_type = 0xff,
    2609                 :            :                 .hdr.icmp_code = 0xff,
    2610                 :            :                 .hdr.icmp_ident = RTE_BE16(0xffff),
    2611                 :            :                 .hdr.icmp_seq_nb = RTE_BE16(0xffff),
    2612                 :            :         };
    2613                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2614         [ #  # ]:          0 :         const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    2615                 :            :                                       MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    2616         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    2617                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    2618                 :            :         int ret;
    2619                 :            : 
    2620         [ #  # ]:          0 :         if (target_protocol != 0xFF && target_protocol != IPPROTO_ICMP)
    2621                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2622                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2623                 :            :                                           "protocol filtering not compatible"
    2624                 :            :                                           " with ICMP layer");
    2625         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    2626         [ #  # ]:          0 :                 if (!(item_flags & l3m))
    2627                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2628                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2629                 :            :                                                   item, "IPv4 is mandatory to filter on ICMP");
    2630                 :            :         }
    2631         [ #  # ]:          0 :         if (item_flags & l4m)
    2632                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2633                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2634                 :            :                                           "multiple L4 layers not supported");
    2635         [ #  # ]:          0 :         if (!mask)
    2636                 :            :                 mask = &nic_mask;
    2637                 :          0 :         ret = mlx5_flow_item_acceptable
    2638                 :            :                 (dev, item, (const uint8_t *)mask,
    2639                 :            :                  (const uint8_t *)&nic_mask,
    2640                 :            :                  sizeof(struct rte_flow_item_icmp),
    2641                 :            :                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2642                 :            :         if (ret < 0)
    2643                 :            :                 return ret;
    2644                 :            :         return 0;
    2645                 :            : }
    2646                 :            : 
    2647                 :            : /**
    2648                 :            :  * Validate Ethernet item.
    2649                 :            :  *
    2650                 :            :  * @param[in] item
    2651                 :            :  *   Item specification.
    2652                 :            :  * @param[in] item_flags
    2653                 :            :  *   Bit-fields that holds the items detected until now.
    2654                 :            :  * @param[out] error
    2655                 :            :  *   Pointer to error structure.
    2656                 :            :  *
    2657                 :            :  * @return
    2658                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2659                 :            :  */
    2660                 :            : int
    2661                 :          0 : mlx5_flow_validate_item_eth(const struct rte_eth_dev *dev,
    2662                 :            :                             const struct rte_flow_item *item,
    2663                 :            :                             uint64_t item_flags, bool ext_vlan_sup,
    2664                 :            :                             struct rte_flow_error *error)
    2665                 :            : {
    2666                 :          0 :         const struct rte_flow_item_eth *mask = item->mask;
    2667                 :          0 :         const struct rte_flow_item_eth nic_mask = {
    2668                 :            :                 .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    2669                 :            :                 .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    2670                 :            :                 .hdr.ether_type = RTE_BE16(0xffff),
    2671                 :            :                 .has_vlan = ext_vlan_sup ? 1 : 0,
    2672                 :            :         };
    2673                 :            :         int ret;
    2674                 :          0 :         int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2675         [ #  # ]:          0 :         const uint64_t ethm = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
    2676                 :            :                                        MLX5_FLOW_LAYER_OUTER_L2;
    2677                 :            : 
    2678         [ #  # ]:          0 :         if (item_flags & ethm)
    2679                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2680                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2681                 :            :                                           "multiple L2 layers not supported");
    2682   [ #  #  #  #  :          0 :         if ((!tunnel && (item_flags & MLX5_FLOW_LAYER_OUTER_L3)) ||
                   #  # ]
    2683         [ #  # ]:          0 :             (tunnel && (item_flags & MLX5_FLOW_LAYER_INNER_L3)))
    2684                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2685                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2686                 :            :                                           "L2 layer should not follow "
    2687                 :            :                                           "L3 layers");
    2688   [ #  #  #  #  :          0 :         if ((!tunnel && (item_flags & MLX5_FLOW_LAYER_OUTER_VLAN)) ||
                   #  # ]
    2689         [ #  # ]:          0 :             (tunnel && (item_flags & MLX5_FLOW_LAYER_INNER_VLAN)))
    2690                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2691                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2692                 :            :                                           "L2 layer should not follow VLAN");
    2693         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_GTP)
    2694                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2695                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2696                 :            :                                           "L2 layer should not follow GTP");
    2697         [ #  # ]:          0 :         if (!mask)
    2698                 :            :                 mask = &rte_flow_item_eth_mask;
    2699                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2700                 :            :                                         (const uint8_t *)&nic_mask,
    2701                 :            :                                         sizeof(struct rte_flow_item_eth),
    2702                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2703                 :          0 :         return ret;
    2704                 :            : }
    2705                 :            : 
    2706                 :            : /**
    2707                 :            :  * Validate VLAN item.
    2708                 :            :  *
    2709                 :            :  * @param[in] item
    2710                 :            :  *   Item specification.
    2711                 :            :  * @param[in] item_flags
    2712                 :            :  *   Bit-fields that holds the items detected until now.
    2713                 :            :  * @param[in] dev
    2714                 :            :  *   Ethernet device flow is being created on.
    2715                 :            :  * @param[out] error
    2716                 :            :  *   Pointer to error structure.
    2717                 :            :  *
    2718                 :            :  * @return
    2719                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2720                 :            :  */
    2721                 :            : int
    2722                 :          0 : mlx5_flow_validate_item_vlan(const struct rte_flow_item *item,
    2723                 :            :                              uint64_t item_flags,
    2724                 :            :                              struct rte_eth_dev *dev,
    2725                 :            :                              struct rte_flow_error *error)
    2726                 :            : {
    2727                 :          0 :         const struct rte_flow_item_vlan *spec = item->spec;
    2728                 :          0 :         const struct rte_flow_item_vlan *mask = item->mask;
    2729                 :          0 :         const struct rte_flow_item_vlan nic_mask = {
    2730                 :            :                 .hdr.vlan_tci = RTE_BE16(UINT16_MAX),
    2731                 :            :                 .hdr.eth_proto = RTE_BE16(UINT16_MAX),
    2732                 :            :         };
    2733                 :            :         uint16_t vlan_tag = 0;
    2734                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2735                 :            :         int ret;
    2736                 :            :         const uint64_t l34m = tunnel ? (MLX5_FLOW_LAYER_INNER_L3 |
    2737         [ #  # ]:          0 :                                         MLX5_FLOW_LAYER_INNER_L4) :
    2738                 :            :                                        (MLX5_FLOW_LAYER_OUTER_L3 |
    2739                 :            :                                         MLX5_FLOW_LAYER_OUTER_L4);
    2740         [ #  # ]:          0 :         const uint64_t vlanm = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
    2741                 :            :                                         MLX5_FLOW_LAYER_OUTER_VLAN;
    2742                 :            : 
    2743         [ #  # ]:          0 :         if (item_flags & vlanm)
    2744                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2745                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2746                 :            :                                           "multiple VLAN layers not supported");
    2747         [ #  # ]:          0 :         else if ((item_flags & l34m) != 0)
    2748                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2749                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2750                 :            :                                           "VLAN cannot follow L3/L4 layer");
    2751         [ #  # ]:          0 :         if (!mask)
    2752                 :            :                 mask = &rte_flow_item_vlan_mask;
    2753                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2754                 :            :                                         (const uint8_t *)&nic_mask,
    2755                 :            :                                         sizeof(struct rte_flow_item_vlan),
    2756                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2757         [ #  # ]:          0 :         if (ret)
    2758                 :            :                 return ret;
    2759   [ #  #  #  # ]:          0 :         if (!tunnel && mask->hdr.vlan_tci != RTE_BE16(0x0fff)) {
    2760                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    2761                 :            : 
    2762         [ #  # ]:          0 :                 if (priv->vmwa_context) {
    2763                 :            :                         /*
    2764                 :            :                          * Non-NULL context means we have a virtual machine
    2765                 :            :                          * and SR-IOV enabled, we have to create VLAN interface
    2766                 :            :                          * to make hypervisor to setup E-Switch vport
    2767                 :            :                          * context correctly. We avoid creating the multiple
    2768                 :            :                          * VLAN interfaces, so we cannot support VLAN tag mask.
    2769                 :            :                          */
    2770                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2771                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2772                 :            :                                                   item,
    2773                 :            :                                                   "VLAN tag mask is not"
    2774                 :            :                                                   " supported in virtual"
    2775                 :            :                                                   " environment");
    2776                 :            :                 }
    2777                 :            :         }
    2778         [ #  # ]:          0 :         if (spec) {
    2779                 :          0 :                 vlan_tag = spec->hdr.vlan_tci;
    2780                 :          0 :                 vlan_tag &= mask->hdr.vlan_tci;
    2781                 :            :         }
    2782                 :            :         /*
    2783                 :            :          * From verbs perspective an empty VLAN is equivalent
    2784                 :            :          * to a packet without VLAN layer.
    2785                 :            :          */
    2786         [ #  # ]:          0 :         if (!vlan_tag)
    2787                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2788                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2789                 :          0 :                                           item->spec,
    2790                 :            :                                           "VLAN cannot be empty");
    2791                 :            :         return 0;
    2792                 :            : }
    2793                 :            : 
    2794                 :            : /**
    2795                 :            :  * Validate IPV4 item.
    2796                 :            :  *
    2797                 :            :  * @param[in] item
    2798                 :            :  *   Item specification.
    2799                 :            :  * @param[in] item_flags
    2800                 :            :  *   Bit-fields that holds the items detected until now.
    2801                 :            :  * @param[in] last_item
    2802                 :            :  *   Previous validated item in the pattern items.
    2803                 :            :  * @param[in] ether_type
    2804                 :            :  *   Type in the ethernet layer header (including dot1q).
    2805                 :            :  * @param[in] acc_mask
    2806                 :            :  *   Acceptable mask, if NULL default internal default mask
    2807                 :            :  *   will be used to check whether item fields are supported.
    2808                 :            :  * @param[in] range_accepted
    2809                 :            :  *   True if range of values is accepted for specific fields, false otherwise.
    2810                 :            :  * @param[out] error
    2811                 :            :  *   Pointer to error structure.
    2812                 :            :  *
    2813                 :            :  * @return
    2814                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2815                 :            :  */
    2816                 :            : int
    2817                 :          0 : mlx5_flow_validate_item_ipv4(const struct rte_eth_dev *dev,
    2818                 :            :                              const struct rte_flow_item *item,
    2819                 :            :                              uint64_t item_flags,
    2820                 :            :                              uint64_t last_item,
    2821                 :            :                              uint16_t ether_type,
    2822                 :            :                              const struct rte_flow_item_ipv4 *acc_mask,
    2823                 :            :                              bool range_accepted,
    2824                 :            :                              struct rte_flow_error *error)
    2825                 :            : {
    2826                 :          0 :         const struct rte_flow_item_ipv4 *mask = item->mask;
    2827                 :          0 :         const struct rte_flow_item_ipv4 *spec = item->spec;
    2828                 :          0 :         const struct rte_flow_item_ipv4 nic_mask = {
    2829                 :            :                 .hdr = {
    2830                 :            :                         .src_addr = RTE_BE32(0xffffffff),
    2831                 :            :                         .dst_addr = RTE_BE32(0xffffffff),
    2832                 :            :                         .type_of_service = 0xff,
    2833                 :            :                         .next_proto_id = 0xff,
    2834                 :            :                 },
    2835                 :            :         };
    2836                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2837         [ #  # ]:          0 :         const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
    2838                 :            :                                       MLX5_FLOW_LAYER_OUTER_L3;
    2839         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    2840                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    2841                 :            :         int ret;
    2842                 :            :         uint8_t next_proto = 0xFF;
    2843                 :            :         const uint64_t l2_vlan = (MLX5_FLOW_LAYER_L2 |
    2844                 :            :                                   MLX5_FLOW_LAYER_OUTER_VLAN |
    2845                 :            :                                   MLX5_FLOW_LAYER_INNER_VLAN);
    2846                 :            : 
    2847         [ #  # ]:          0 :         if ((last_item & l2_vlan) && ether_type &&
    2848         [ #  # ]:          0 :             ether_type != RTE_ETHER_TYPE_IPV4)
    2849                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2850                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2851                 :            :                                           "IPv4 cannot follow L2/VLAN layer "
    2852                 :            :                                           "which ether type is not IPv4");
    2853         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_IPIP) {
    2854         [ #  # ]:          0 :                 if (mask && spec)
    2855                 :          0 :                         next_proto = mask->hdr.next_proto_id &
    2856                 :          0 :                                      spec->hdr.next_proto_id;
    2857         [ #  # ]:          0 :                 if (next_proto == IPPROTO_IPIP || next_proto == IPPROTO_IPV6)
    2858                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2859                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2860                 :            :                                                   item,
    2861                 :            :                                                   "multiple tunnel "
    2862                 :            :                                                   "not supported");
    2863                 :            :         }
    2864         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_IPV6_ENCAP)
    2865                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2866                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2867                 :            :                                           "wrong tunnel type - IPv6 specified "
    2868                 :            :                                           "but IPv4 item provided");
    2869         [ #  # ]:          0 :         if (item_flags & l3m)
    2870                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2871                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2872                 :            :                                           "multiple L3 layers not supported");
    2873         [ #  # ]:          0 :         else if (item_flags & l4m)
    2874                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2875                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2876                 :            :                                           "L3 cannot follow an L4 layer.");
    2877         [ #  # ]:          0 :         else if ((item_flags & MLX5_FLOW_LAYER_NVGRE) &&
    2878                 :            :                   !(item_flags & MLX5_FLOW_LAYER_INNER_L2))
    2879                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2880                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2881                 :            :                                           "L3 cannot follow an NVGRE layer.");
    2882         [ #  # ]:          0 :         if (!mask)
    2883                 :            :                 mask = &rte_flow_item_ipv4_mask;
    2884         [ #  # ]:          0 :         else if (mask->hdr.next_proto_id != 0 &&
    2885                 :            :                  mask->hdr.next_proto_id != 0xff)
    2886                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2887                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,
    2888                 :            :                                           "partial mask is not supported"
    2889                 :            :                                           " for protocol");
    2890         [ #  # ]:          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2891                 :            :                                         acc_mask ? (const uint8_t *)acc_mask
    2892                 :            :                                                  : (const uint8_t *)&nic_mask,
    2893                 :            :                                         sizeof(struct rte_flow_item_ipv4),
    2894                 :            :                                         range_accepted, error);
    2895                 :            :         if (ret < 0)
    2896                 :            :                 return ret;
    2897                 :            :         return 0;
    2898                 :            : }
    2899                 :            : 
    2900                 :            : /**
    2901                 :            :  * Validate IPV6 item.
    2902                 :            :  *
    2903                 :            :  * @param[in] item
    2904                 :            :  *   Item specification.
    2905                 :            :  * @param[in] item_flags
    2906                 :            :  *   Bit-fields that holds the items detected until now.
    2907                 :            :  * @param[in] last_item
    2908                 :            :  *   Previous validated item in the pattern items.
    2909                 :            :  * @param[in] ether_type
    2910                 :            :  *   Type in the ethernet layer header (including dot1q).
    2911                 :            :  * @param[in] acc_mask
    2912                 :            :  *   Acceptable mask, if NULL default internal default mask
    2913                 :            :  *   will be used to check whether item fields are supported.
    2914                 :            :  * @param[out] error
    2915                 :            :  *   Pointer to error structure.
    2916                 :            :  *
    2917                 :            :  * @return
    2918                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2919                 :            :  */
    2920                 :            : int
    2921                 :          0 : mlx5_flow_validate_item_ipv6(const struct rte_eth_dev *dev,
    2922                 :            :                              const struct rte_flow_item *item,
    2923                 :            :                              uint64_t item_flags,
    2924                 :            :                              uint64_t last_item,
    2925                 :            :                              uint16_t ether_type,
    2926                 :            :                              const struct rte_flow_item_ipv6 *acc_mask,
    2927                 :            :                              struct rte_flow_error *error)
    2928                 :            : {
    2929                 :          0 :         const struct rte_flow_item_ipv6 *mask = item->mask;
    2930                 :          0 :         const struct rte_flow_item_ipv6 *spec = item->spec;
    2931                 :          0 :         const struct rte_flow_item_ipv6 nic_mask = {
    2932                 :            :                 .hdr = {
    2933                 :            :                         .src_addr = RTE_IPV6_MASK_FULL,
    2934                 :            :                         .dst_addr = RTE_IPV6_MASK_FULL,
    2935                 :            :                         .vtc_flow = RTE_BE32(0xffffffff),
    2936                 :            :                         .proto = 0xff,
    2937                 :            :                 },
    2938                 :            :         };
    2939                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2940         [ #  # ]:          0 :         const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
    2941                 :            :                                       MLX5_FLOW_LAYER_OUTER_L3;
    2942         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    2943                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    2944                 :            :         int ret;
    2945                 :            :         uint8_t next_proto = 0xFF;
    2946                 :            :         const uint64_t l2_vlan = (MLX5_FLOW_LAYER_L2 |
    2947                 :            :                                   MLX5_FLOW_LAYER_OUTER_VLAN |
    2948                 :            :                                   MLX5_FLOW_LAYER_INNER_VLAN);
    2949                 :            : 
    2950         [ #  # ]:          0 :         if ((last_item & l2_vlan) && ether_type &&
    2951         [ #  # ]:          0 :             ether_type != RTE_ETHER_TYPE_IPV6)
    2952                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2953                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2954                 :            :                                           "IPv6 cannot follow L2/VLAN layer "
    2955                 :            :                                           "which ether type is not IPv6");
    2956   [ #  #  #  #  :          0 :         if (mask && mask->hdr.proto == UINT8_MAX && spec)
                   #  # ]
    2957                 :          0 :                 next_proto = spec->hdr.proto;
    2958         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_IPIP) {
    2959         [ #  # ]:          0 :                 if (next_proto == IPPROTO_IPIP || next_proto == IPPROTO_IPV6)
    2960                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2961                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2962                 :            :                                                   item,
    2963                 :            :                                                   "multiple tunnel "
    2964                 :            :                                                   "not supported");
    2965                 :            :         }
    2966                 :          0 :         if (next_proto == IPPROTO_HOPOPTS  ||
    2967         [ #  # ]:          0 :             next_proto == IPPROTO_ROUTING  ||
    2968                 :            :             next_proto == IPPROTO_FRAGMENT ||
    2969                 :            :             next_proto == IPPROTO_AH       ||
    2970         [ #  # ]:          0 :             next_proto == IPPROTO_DSTOPTS  ||
    2971         [ #  # ]:          0 :             (!mlx5_hws_active(dev) && next_proto == IPPROTO_ESP))
    2972                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2973                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2974                 :            :                                           "IPv6 proto (next header) should "
    2975                 :            :                                           "not be set as extension header");
    2976         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_IPIP)
    2977                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2978                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2979                 :            :                                           "wrong tunnel type - IPv4 specified "
    2980                 :            :                                           "but IPv6 item provided");
    2981         [ #  # ]:          0 :         if (item_flags & l3m)
    2982                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2983                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2984                 :            :                                           "multiple L3 layers not supported");
    2985         [ #  # ]:          0 :         else if (item_flags & l4m)
    2986                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2987                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2988                 :            :                                           "L3 cannot follow an L4 layer.");
    2989         [ #  # ]:          0 :         else if ((item_flags & MLX5_FLOW_LAYER_NVGRE) &&
    2990                 :            :                   !(item_flags & MLX5_FLOW_LAYER_INNER_L2))
    2991                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2992                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2993                 :            :                                           "L3 cannot follow an NVGRE layer.");
    2994         [ #  # ]:          0 :         if (!mask)
    2995                 :            :                 mask = &rte_flow_item_ipv6_mask;
    2996         [ #  # ]:          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2997                 :            :                                         acc_mask ? (const uint8_t *)acc_mask
    2998                 :            :                                                  : (const uint8_t *)&nic_mask,
    2999                 :            :                                         sizeof(struct rte_flow_item_ipv6),
    3000                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3001                 :            :         if (ret < 0)
    3002                 :            :                 return ret;
    3003                 :            :         return 0;
    3004                 :            : }
    3005                 :            : 
    3006                 :            : /**
    3007                 :            :  * Validate UDP item.
    3008                 :            :  *
    3009                 :            :  * @param[in] item
    3010                 :            :  *   Item specification.
    3011                 :            :  * @param[in] item_flags
    3012                 :            :  *   Bit-fields that holds the items detected until now.
    3013                 :            :  * @param[in] target_protocol
    3014                 :            :  *   The next protocol in the previous item.
    3015                 :            :  * @param[in] flow_mask
    3016                 :            :  *   mlx5 flow-specific (DV, verbs, etc.) supported header fields mask.
    3017                 :            :  * @param[out] error
    3018                 :            :  *   Pointer to error structure.
    3019                 :            :  *
    3020                 :            :  * @return
    3021                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3022                 :            :  */
    3023                 :            : int
    3024                 :          0 : mlx5_flow_validate_item_udp(const struct rte_eth_dev *dev,
    3025                 :            :                             const struct rte_flow_item *item,
    3026                 :            :                             uint64_t item_flags,
    3027                 :            :                             uint8_t target_protocol,
    3028                 :            :                             struct rte_flow_error *error)
    3029                 :            : {
    3030                 :          0 :         const struct rte_flow_item_udp *mask = item->mask;
    3031                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    3032         [ #  # ]:          0 :         const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
    3033                 :            :                                       MLX5_FLOW_LAYER_OUTER_L3;
    3034         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    3035                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    3036                 :            :         int ret;
    3037                 :            : 
    3038         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    3039         [ #  # ]:          0 :                 if (target_protocol != 0xff && target_protocol != IPPROTO_UDP)
    3040                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3041                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3042                 :            :                                                   item, "protocol filtering not compatible with UDP layer");
    3043         [ #  # ]:          0 :                 if (!(item_flags & l3m))
    3044                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3045                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3046                 :            :                                                   item,
    3047                 :            :                                                   "L3 is mandatory to filter on L4");
    3048                 :            :         }
    3049         [ #  # ]:          0 :         if (item_flags & l4m)
    3050                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3051                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3052                 :            :                                           "multiple L4 layers not supported");
    3053         [ #  # ]:          0 :         if (!mask)
    3054                 :            :                 mask = &rte_flow_item_udp_mask;
    3055                 :          0 :         ret = mlx5_flow_item_acceptable
    3056                 :            :                 (dev, item, (const uint8_t *)mask,
    3057                 :            :                  (const uint8_t *)&rte_flow_item_udp_mask,
    3058                 :            :                  sizeof(struct rte_flow_item_udp), MLX5_ITEM_RANGE_NOT_ACCEPTED,
    3059                 :            :                  error);
    3060                 :            :         if (ret < 0)
    3061                 :            :                 return ret;
    3062                 :            :         return 0;
    3063                 :            : }
    3064                 :            : 
    3065                 :            : /**
    3066                 :            :  * Validate TCP item.
    3067                 :            :  *
    3068                 :            :  * @param[in] item
    3069                 :            :  *   Item specification.
    3070                 :            :  * @param[in] item_flags
    3071                 :            :  *   Bit-fields that holds the items detected until now.
    3072                 :            :  * @param[in] target_protocol
    3073                 :            :  *   The next protocol in the previous item.
    3074                 :            :  * @param[out] error
    3075                 :            :  *   Pointer to error structure.
    3076                 :            :  *
    3077                 :            :  * @return
    3078                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3079                 :            :  */
    3080                 :            : int
    3081                 :          0 : mlx5_flow_validate_item_tcp(const struct rte_eth_dev *dev,
    3082                 :            :                             const struct rte_flow_item *item,
    3083                 :            :                             uint64_t item_flags,
    3084                 :            :                             uint8_t target_protocol,
    3085                 :            :                             const struct rte_flow_item_tcp *flow_mask,
    3086                 :            :                             struct rte_flow_error *error)
    3087                 :            : {
    3088                 :          0 :         const struct rte_flow_item_tcp *mask = item->mask;
    3089                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    3090         [ #  # ]:          0 :         const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
    3091                 :            :                                       MLX5_FLOW_LAYER_OUTER_L3;
    3092         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    3093                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    3094                 :            :         int ret;
    3095                 :            : 
    3096                 :            :         MLX5_ASSERT(flow_mask);
    3097         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    3098         [ #  # ]:          0 :                 if (target_protocol != 0xff && target_protocol != IPPROTO_TCP)
    3099                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3100                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3101                 :            :                                                   item, "protocol filtering not compatible with TCP layer");
    3102         [ #  # ]:          0 :                 if (!(item_flags & l3m))
    3103                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3104                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3105                 :            :                                                   item, "L3 is mandatory to filter on L4");
    3106                 :            :         }
    3107         [ #  # ]:          0 :         if (item_flags & l4m)
    3108                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3109                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3110                 :            :                                           "multiple L4 layers not supported");
    3111         [ #  # ]:          0 :         if (!mask)
    3112                 :            :                 mask = &rte_flow_item_tcp_mask;
    3113                 :          0 :         ret = mlx5_flow_item_acceptable
    3114                 :            :                 (dev, item, (const uint8_t *)mask,
    3115                 :            :                  (const uint8_t *)flow_mask,
    3116                 :            :                  sizeof(struct rte_flow_item_tcp), MLX5_ITEM_RANGE_NOT_ACCEPTED,
    3117                 :            :                  error);
    3118                 :            :         if (ret < 0)
    3119                 :            :                 return ret;
    3120                 :            :         return 0;
    3121                 :            : }
    3122                 :            : 
    3123                 :            : /**
    3124                 :            :  * Validate VXLAN item.
    3125                 :            :  *
    3126                 :            :  * @param[in] dev
    3127                 :            :  *   Pointer to the Ethernet device structure.
    3128                 :            :  * @param[in] udp_dport
    3129                 :            :  *   UDP destination port
    3130                 :            :  * @param[in] item
    3131                 :            :  *   Item specification.
    3132                 :            :  * @param[in] item_flags
    3133                 :            :  *   Bit-fields that holds the items detected until now.
    3134                 :            :  * @param root
    3135                 :            :  *   Whether action is on root table.
    3136                 :            :  * @param[out] error
    3137                 :            :  *   Pointer to error structure.
    3138                 :            :  *
    3139                 :            :  * @return
    3140                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3141                 :            :  */
    3142                 :            : int
    3143                 :          0 : mlx5_flow_validate_item_vxlan(struct rte_eth_dev *dev,
    3144                 :            :                               uint16_t udp_dport,
    3145                 :            :                               const struct rte_flow_item *item,
    3146                 :            :                               uint64_t item_flags,
    3147                 :            :                               bool root,
    3148                 :            :                               struct rte_flow_error *error)
    3149                 :            : {
    3150                 :          0 :         const struct rte_flow_item_vxlan *spec = item->spec;
    3151                 :          0 :         const struct rte_flow_item_vxlan *mask = item->mask;
    3152                 :            :         int ret;
    3153                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3154                 :            :         union vni {
    3155                 :            :                 uint32_t vlan_id;
    3156                 :            :                 uint8_t vni[4];
    3157                 :          0 :         } id = { .vlan_id = 0, };
    3158                 :          0 :         const struct rte_flow_item_vxlan nic_mask = {
    3159                 :            :                 .hdr.vni =  { 0xff, 0xff, 0xff },
    3160                 :            :                 .hdr.rsvd1 = 0xff,
    3161                 :            :         };
    3162                 :            :         const struct rte_flow_item_vxlan *valid_mask;
    3163                 :            : 
    3164         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
    3165                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3166                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3167                 :            :                                           "multiple tunnel layers not"
    3168                 :            :                                           " supported");
    3169                 :            :         /* HWS can match entire VXLAN, VXLAN-GBP and VXLAN-GPE headers */
    3170         [ #  # ]:          0 :         if (mlx5_hws_active(dev))
    3171                 :            :                 return 0;
    3172                 :            :         valid_mask = &rte_flow_item_vxlan_mask;
    3173                 :            :         /*
    3174                 :            :          * Verify only UDPv4 is present as defined in
    3175                 :            :          * https://tools.ietf.org/html/rfc7348
    3176                 :            :          */
    3177         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP))
    3178                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3179                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    3180                 :            :                                           item, "no outer UDP layer found");
    3181         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER))
    3182                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3183                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3184                 :            :                                           "VXLAN tunnel must be fully defined");
    3185         [ #  # ]:          0 :         if (!mask)
    3186                 :            :                 mask = &rte_flow_item_vxlan_mask;
    3187                 :            : 
    3188         [ #  # ]:          0 :         if (priv->sh->steering_format_version !=
    3189                 :            :             MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 ||
    3190         [ #  # ]:          0 :             !udp_dport || udp_dport == MLX5_UDP_PORT_VXLAN) {
    3191                 :            :                 /* non-root table */
    3192   [ #  #  #  # ]:          0 :                 if (!root && priv->sh->misc5_cap)
    3193                 :            :                         valid_mask = &nic_mask;
    3194                 :            :                 /* Group zero in NIC domain */
    3195   [ #  #  #  # ]:          0 :                 if (!root && priv->sh->tunnel_header_0_1)
    3196                 :            :                         valid_mask = &nic_mask;
    3197                 :            :         }
    3198                 :          0 :         ret = mlx5_flow_item_acceptable
    3199                 :            :                 (dev, item, (const uint8_t *)mask,
    3200                 :            :                  (const uint8_t *)valid_mask,
    3201                 :            :                  sizeof(struct rte_flow_item_vxlan),
    3202                 :            :                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3203                 :            :         if (ret < 0)
    3204                 :            :                 return ret;
    3205                 :            :         if (spec) {
    3206                 :            :                 memcpy(&id.vni[1], spec->hdr.vni, 3);
    3207                 :            :                 memcpy(&id.vni[1], mask->hdr.vni, 3);
    3208                 :            :         }
    3209                 :            :         return 0;
    3210                 :            : }
    3211                 :            : 
    3212                 :            : /**
    3213                 :            :  * Validate VXLAN_GPE item.
    3214                 :            :  *
    3215                 :            :  * @param[in] item
    3216                 :            :  *   Item specification.
    3217                 :            :  * @param[in] item_flags
    3218                 :            :  *   Bit-fields that holds the items detected until now.
    3219                 :            :  * @param[in] priv
    3220                 :            :  *   Pointer to the private data structure.
    3221                 :            :  * @param[in] target_protocol
    3222                 :            :  *   The next protocol in the previous item.
    3223                 :            :  * @param[out] error
    3224                 :            :  *   Pointer to error structure.
    3225                 :            :  *
    3226                 :            :  * @return
    3227                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3228                 :            :  */
    3229                 :            : int
    3230                 :          0 : mlx5_flow_validate_item_vxlan_gpe(const struct rte_flow_item *item,
    3231                 :            :                                   uint64_t item_flags,
    3232                 :            :                                   struct rte_eth_dev *dev,
    3233                 :            :                                   struct rte_flow_error *error)
    3234                 :            : {
    3235                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3236                 :            :         const struct rte_flow_item_vxlan_gpe *spec = item->spec;
    3237                 :          0 :         const struct rte_flow_item_vxlan_gpe *mask = item->mask;
    3238                 :            :         int ret;
    3239                 :            :         union vni {
    3240                 :            :                 uint32_t vlan_id;
    3241                 :            :                 uint8_t vni[4];
    3242                 :          0 :         } id = { .vlan_id = 0, };
    3243                 :            : 
    3244                 :          0 :         struct rte_flow_item_vxlan_gpe nic_mask = {
    3245                 :            :                 .vni =  { 0xff, 0xff, 0xff },
    3246                 :            :                 .protocol = 0xff,
    3247                 :            :                 .flags = 0xff,
    3248                 :            :         };
    3249                 :            : 
    3250         [ #  # ]:          0 :         if (!priv->sh->config.l3_vxlan_en)
    3251                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3252                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3253                 :            :                                           "L3 VXLAN is not enabled by device"
    3254                 :            :                                           " parameter and/or not configured in"
    3255                 :            :                                           " firmware");
    3256         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
    3257                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3258                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3259                 :            :                                           "multiple tunnel layers not"
    3260                 :            :                                           " supported");
    3261                 :            :         /*
    3262                 :            :          * Verify only UDPv4 is present as defined in
    3263                 :            :          * https://tools.ietf.org/html/rfc7348
    3264                 :            :          */
    3265         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    3266         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP))
    3267                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3268                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3269                 :            :                                                   item, "no outer UDP layer found");
    3270                 :            :         }
    3271         [ #  # ]:          0 :         if (!mask)
    3272                 :            :                 mask = &rte_flow_item_vxlan_gpe_mask;
    3273         [ #  # ]:          0 :         if (mlx5_hws_active(dev) ||
    3274         [ #  # ]:          0 :             (priv->sh->misc5_cap && priv->sh->tunnel_header_0_1)) {
    3275                 :          0 :                 nic_mask.rsvd0[0] = 0xff;
    3276                 :          0 :                 nic_mask.rsvd0[1] = 0xff;
    3277                 :          0 :                 nic_mask.rsvd1 = 0xff;
    3278                 :            :         }
    3279                 :          0 :         ret = mlx5_flow_item_acceptable
    3280                 :            :                 (dev, item, (const uint8_t *)mask,
    3281                 :            :                  (const uint8_t *)&nic_mask,
    3282                 :            :                  sizeof(struct rte_flow_item_vxlan_gpe),
    3283                 :            :                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3284         [ #  # ]:          0 :         if (ret < 0)
    3285                 :            :                 return ret;
    3286                 :            :         if (spec) {
    3287                 :            :                 memcpy(&id.vni[1], spec->hdr.vni, 3);
    3288                 :            :                 memcpy(&id.vni[1], mask->hdr.vni, 3);
    3289                 :            :         }
    3290         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER))
    3291                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3292                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3293                 :            :                                           "VXLAN-GPE tunnel must be fully"
    3294                 :            :                                           " defined");
    3295                 :            :         return 0;
    3296                 :            : }
    3297                 :            : /**
    3298                 :            :  * Validate GRE Key item.
    3299                 :            :  *
    3300                 :            :  * @param[in] item
    3301                 :            :  *   Item specification.
    3302                 :            :  * @param[in] item_flags
    3303                 :            :  *   Bit flags to mark detected items.
    3304                 :            :  * @param[in] gre_item
    3305                 :            :  *   Pointer to gre_item
    3306                 :            :  * @param[out] error
    3307                 :            :  *   Pointer to error structure.
    3308                 :            :  *
    3309                 :            :  * @return
    3310                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3311                 :            :  */
    3312                 :            : int
    3313                 :          0 : mlx5_flow_validate_item_gre_key(const struct rte_eth_dev *dev,
    3314                 :            :                                 const struct rte_flow_item *item,
    3315                 :            :                                 uint64_t item_flags,
    3316                 :            :                                 const struct rte_flow_item *gre_item,
    3317                 :            :                                 struct rte_flow_error *error)
    3318                 :            : {
    3319                 :          0 :         const rte_be32_t *mask = item->mask;
    3320                 :            :         int ret = 0;
    3321                 :          0 :         rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
    3322                 :            :         const struct rte_flow_item_gre *gre_spec;
    3323                 :            :         const struct rte_flow_item_gre *gre_mask;
    3324                 :            : 
    3325         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_GRE_KEY)
    3326                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3327                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3328                 :            :                                           "Multiple GRE key not support");
    3329         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_GRE))
    3330                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3331                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3332                 :            :                                           "No preceding GRE header");
    3333         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_INNER)
    3334                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3335                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3336                 :            :                                           "GRE key following a wrong item");
    3337                 :          0 :         gre_mask = gre_item->mask;
    3338         [ #  # ]:          0 :         if (!gre_mask)
    3339                 :            :                 gre_mask = &rte_flow_item_gre_mask;
    3340                 :          0 :         gre_spec = gre_item->spec;
    3341   [ #  #  #  # ]:          0 :         if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) &&
    3342         [ #  # ]:          0 :                          !(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000)))
    3343                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3344                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3345                 :            :                                           "Key bit must be on");
    3346                 :            : 
    3347         [ #  # ]:          0 :         if (!mask)
    3348                 :            :                 mask = &gre_key_default_mask;
    3349                 :          0 :         ret = mlx5_flow_item_acceptable
    3350                 :            :                 (dev, item, (const uint8_t *)mask,
    3351                 :            :                  (const uint8_t *)&gre_key_default_mask,
    3352                 :            :                  sizeof(rte_be32_t), MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3353                 :          0 :         return ret;
    3354                 :            : }
    3355                 :            : 
    3356                 :            : /**
    3357                 :            :  * Validate GRE optional item.
    3358                 :            :  *
    3359                 :            :  * @param[in] dev
    3360                 :            :  *   Pointer to the Ethernet device structure.
    3361                 :            :  * @param[in] item
    3362                 :            :  *   Item specification.
    3363                 :            :  * @param[in] item_flags
    3364                 :            :  *   Bit flags to mark detected items.
    3365                 :            :  * @param[in] attr
    3366                 :            :  *   Flow rule attributes.
    3367                 :            :  * @param[in] gre_item
    3368                 :            :  *   Pointer to gre_item
    3369                 :            :  * @param[out] error
    3370                 :            :  *   Pointer to error structure.
    3371                 :            :  *
    3372                 :            :  * @return
    3373                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3374                 :            :  */
    3375                 :            : int
    3376                 :          0 : mlx5_flow_validate_item_gre_option(struct rte_eth_dev *dev,
    3377                 :            :                                    const struct rte_flow_item *item,
    3378                 :            :                                    uint64_t item_flags,
    3379                 :            :                                    const struct rte_flow_attr *attr,
    3380                 :            :                                    const struct rte_flow_item *gre_item,
    3381                 :            :                                    struct rte_flow_error *error)
    3382                 :            : {
    3383                 :          0 :         const struct rte_flow_item_gre *gre_spec = gre_item->spec;
    3384                 :          0 :         const struct rte_flow_item_gre *gre_mask = gre_item->mask;
    3385                 :          0 :         const struct rte_flow_item_gre_opt *spec = item->spec;
    3386                 :          0 :         const struct rte_flow_item_gre_opt *mask = item->mask;
    3387                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3388                 :            :         int ret = 0;
    3389                 :          0 :         struct rte_flow_item_gre_opt nic_mask = {
    3390                 :            :                 .checksum_rsvd = {
    3391                 :            :                         .checksum = RTE_BE16(UINT16_MAX),
    3392                 :            :                         .reserved1 = 0x0,
    3393                 :            :                 },
    3394                 :            :                 .key = {
    3395                 :            :                         .key = RTE_BE32(UINT32_MAX),
    3396                 :            :                 },
    3397                 :            :                 .sequence = {
    3398                 :            :                         .sequence = RTE_BE32(UINT32_MAX),
    3399                 :            :                 },
    3400                 :            :         };
    3401                 :            : 
    3402         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_GRE))
    3403                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3404                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3405                 :            :                                           "No preceding GRE header");
    3406         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_INNER)
    3407                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3408                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3409                 :            :                                           "GRE option following a wrong item");
    3410   [ #  #  #  #  :          0 :         if ((!spec && !mlx5_hws_active(dev)) || !mask)
                   #  # ]
    3411                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3412                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3413                 :            :                                           "At least one field gre_option(checksum/key/sequence) must be specified");
    3414         [ #  # ]:          0 :         if (!gre_mask)
    3415                 :            :                 gre_mask = &rte_flow_item_gre_mask;
    3416         [ #  # ]:          0 :         if (mask->checksum_rsvd.checksum)
    3417   [ #  #  #  # ]:          0 :                 if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x8000)) &&
    3418         [ #  # ]:          0 :                                  !(gre_spec->c_rsvd0_ver & RTE_BE16(0x8000)))
    3419                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3420                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3421                 :            :                                                   item,
    3422                 :            :                                                   "Checksum bit must be on");
    3423         [ #  # ]:          0 :         if (mask->key.key)
    3424   [ #  #  #  # ]:          0 :                 if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) &&
    3425         [ #  # ]:          0 :                                  !(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000)))
    3426                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3427                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3428                 :            :                                                   item, "Key bit must be on");
    3429         [ #  # ]:          0 :         if (mask->sequence.sequence)
    3430   [ #  #  #  # ]:          0 :                 if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x1000)) &&
    3431         [ #  # ]:          0 :                                  !(gre_spec->c_rsvd0_ver & RTE_BE16(0x1000)))
    3432                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3433                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3434                 :            :                                                   item,
    3435                 :            :                                                   "Sequence bit must be on");
    3436         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    3437   [ #  #  #  # ]:          0 :                 if (mask->checksum_rsvd.checksum || mask->sequence.sequence) {
    3438         [ #  # ]:          0 :                         if (priv->sh->steering_format_version ==
    3439                 :          0 :                             MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 ||
    3440         [ #  # ]:          0 :                             ((attr->group ||
    3441   [ #  #  #  # ]:          0 :                               (attr->transfer && priv->fdb_def_rule)) &&
    3442         [ #  # ]:          0 :                              !priv->sh->misc5_cap) ||
    3443         [ #  # ]:          0 :                             (!(priv->sh->tunnel_header_0_1 &&
    3444         [ #  # ]:          0 :                                priv->sh->tunnel_header_2_3) &&
    3445                 :          0 :                              !attr->group &&
    3446   [ #  #  #  # ]:          0 :                              (!attr->transfer || !priv->fdb_def_rule)))
    3447                 :          0 :                                 return rte_flow_error_set
    3448                 :            :                                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
    3449                 :            :                                          item, "Checksum/Sequence not supported");
    3450                 :            :                 }
    3451                 :            :         }
    3452                 :          0 :         ret = mlx5_flow_item_acceptable
    3453                 :            :                 (dev, item, (const uint8_t *)mask,
    3454                 :            :                  (const uint8_t *)&nic_mask,
    3455                 :            :                  sizeof(struct rte_flow_item_gre_opt),
    3456                 :            :                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3457                 :          0 :         return ret;
    3458                 :            : }
    3459                 :            : 
    3460                 :            : /**
    3461                 :            :  * Validate GRE item.
    3462                 :            :  *
    3463                 :            :  * @param[in] item
    3464                 :            :  *   Item specification.
    3465                 :            :  * @param[in] item_flags
    3466                 :            :  *   Bit flags to mark detected items.
    3467                 :            :  * @param[in] target_protocol
    3468                 :            :  *   The next protocol in the previous item.
    3469                 :            :  * @param[out] error
    3470                 :            :  *   Pointer to error structure.
    3471                 :            :  *
    3472                 :            :  * @return
    3473                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3474                 :            :  */
    3475                 :            : int
    3476                 :          0 : mlx5_flow_validate_item_gre(const struct rte_eth_dev *dev,
    3477                 :            :                             const struct rte_flow_item *item,
    3478                 :            :                             uint64_t item_flags,
    3479                 :            :                             uint8_t target_protocol,
    3480                 :            :                             struct rte_flow_error *error)
    3481                 :            : {
    3482                 :            :         const struct rte_flow_item_gre *spec __rte_unused = item->spec;
    3483                 :          0 :         const struct rte_flow_item_gre *mask = item->mask;
    3484                 :            :         int ret;
    3485                 :          0 :         const struct rte_flow_item_gre nic_mask = {
    3486                 :            :                 .c_rsvd0_ver = RTE_BE16(0xB000),
    3487                 :            :                 .protocol = RTE_BE16(UINT16_MAX),
    3488                 :            :         };
    3489                 :            : 
    3490         [ #  # ]:          0 :         if (target_protocol != 0xff && target_protocol != IPPROTO_GRE)
    3491                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3492                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3493                 :            :                                           "protocol filtering not compatible"
    3494                 :            :                                           " with this GRE layer");
    3495         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
    3496                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3497                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3498                 :            :                                           "multiple tunnel layers not"
    3499                 :            :                                           " supported");
    3500         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    3501         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3))
    3502                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3503                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3504                 :            :                                                   item, "L3 Layer is missing");
    3505                 :            :         }
    3506         [ #  # ]:          0 :         if (!mask)
    3507                 :            :                 mask = &rte_flow_item_gre_mask;
    3508                 :          0 :         ret = mlx5_flow_item_acceptable
    3509                 :            :                 (dev, item, (const uint8_t *)mask,
    3510                 :            :                  (const uint8_t *)&nic_mask,
    3511                 :            :                  sizeof(struct rte_flow_item_gre), MLX5_ITEM_RANGE_NOT_ACCEPTED,
    3512                 :            :                  error);
    3513                 :            :         if (ret < 0)
    3514                 :            :                 return ret;
    3515                 :            : #ifndef HAVE_MLX5DV_DR
    3516                 :            : #ifndef HAVE_IBV_DEVICE_MPLS_SUPPORT
    3517                 :            :         if (spec && (spec->protocol & mask->protocol))
    3518                 :            :                 return rte_flow_error_set(error, ENOTSUP,
    3519                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3520                 :            :                                           "without MPLS support the"
    3521                 :            :                                           " specification cannot be used for"
    3522                 :            :                                           " filtering");
    3523                 :            : #endif
    3524                 :            : #endif
    3525                 :            :         return 0;
    3526                 :            : }
    3527                 :            : 
    3528                 :            : /**
    3529                 :            :  * Validate Geneve item.
    3530                 :            :  *
    3531                 :            :  * @param[in] item
    3532                 :            :  *   Item specification.
    3533                 :            :  * @param[in] itemFlags
    3534                 :            :  *   Bit-fields that holds the items detected until now.
    3535                 :            :  * @param[in] enPriv
    3536                 :            :  *   Pointer to the private data structure.
    3537                 :            :  * @param[out] error
    3538                 :            :  *   Pointer to error structure.
    3539                 :            :  *
    3540                 :            :  * @return
    3541                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3542                 :            :  */
    3543                 :            : 
    3544                 :            : int
    3545                 :          0 : mlx5_flow_validate_item_geneve(const struct rte_flow_item *item,
    3546                 :            :                                uint64_t item_flags,
    3547                 :            :                                struct rte_eth_dev *dev,
    3548                 :            :                                struct rte_flow_error *error)
    3549                 :            : {
    3550                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3551                 :          0 :         const struct rte_flow_item_geneve *spec = item->spec;
    3552                 :          0 :         const struct rte_flow_item_geneve *mask = item->mask;
    3553                 :            :         int ret;
    3554                 :            :         uint16_t gbhdr;
    3555         [ #  # ]:          0 :         uint8_t opt_len = priv->sh->cdev->config.hca_attr.geneve_max_opt_len ?
    3556                 :            :                           MLX5_GENEVE_OPT_LEN_1 : MLX5_GENEVE_OPT_LEN_0;
    3557                 :          0 :         const struct rte_flow_item_geneve nic_mask = {
    3558                 :            :                 .ver_opt_len_o_c_rsvd0 = RTE_BE16(0x3f80),
    3559                 :            :                 .vni =  { 0xff, 0xff, 0xff },
    3560                 :            :                 .protocol = RTE_BE16(UINT16_MAX),
    3561                 :            :         };
    3562                 :            : 
    3563         [ #  # ]:          0 :         if (!priv->sh->cdev->config.hca_attr.tunnel_stateless_geneve_rx)
    3564                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3565                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3566                 :            :                                           "L3 Geneve is not enabled by device"
    3567                 :            :                                           " parameter and/or not configured in"
    3568                 :            :                                           " firmware");
    3569         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
    3570                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3571                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3572                 :            :                                           "multiple tunnel layers not"
    3573                 :            :                                           " supported");
    3574                 :            :         /*
    3575                 :            :          * Verify only UDPv4 is present as defined in
    3576                 :            :          * https://tools.ietf.org/html/rfc7348
    3577                 :            :          */
    3578         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP))
    3579                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3580                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3581                 :            :                                           "no outer UDP layer found");
    3582         [ #  # ]:          0 :         if (!mask)
    3583                 :            :                 mask = &rte_flow_item_geneve_mask;
    3584                 :          0 :         ret = mlx5_flow_item_acceptable
    3585                 :            :                                   (dev, item, (const uint8_t *)mask,
    3586                 :            :                                    (const uint8_t *)&nic_mask,
    3587                 :            :                                    sizeof(struct rte_flow_item_geneve),
    3588                 :            :                                    MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3589         [ #  # ]:          0 :         if (ret)
    3590                 :            :                 return ret;
    3591         [ #  # ]:          0 :         if (spec) {
    3592         [ #  # ]:          0 :                 gbhdr = rte_be_to_cpu_16(spec->ver_opt_len_o_c_rsvd0);
    3593         [ #  # ]:          0 :                 if (MLX5_GENEVE_VER_VAL(gbhdr) ||
    3594   [ #  #  #  # ]:          0 :                      MLX5_GENEVE_CRITO_VAL(gbhdr) ||
    3595         [ #  # ]:          0 :                      MLX5_GENEVE_RSVD_VAL(gbhdr) || spec->rsvd1)
    3596                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3597                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3598                 :            :                                                   item,
    3599                 :            :                                                   "Geneve protocol unsupported"
    3600                 :            :                                                   " fields are being used");
    3601         [ #  # ]:          0 :                 if (MLX5_GENEVE_OPTLEN_VAL(gbhdr) > opt_len)
    3602                 :          0 :                         return rte_flow_error_set
    3603                 :            :                                         (error, ENOTSUP,
    3604                 :            :                                          RTE_FLOW_ERROR_TYPE_ITEM,
    3605                 :            :                                          item,
    3606                 :            :                                          "Unsupported Geneve options length");
    3607                 :            :         }
    3608         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER))
    3609                 :          0 :                 return rte_flow_error_set
    3610                 :            :                                     (error, ENOTSUP,
    3611                 :            :                                      RTE_FLOW_ERROR_TYPE_ITEM, item,
    3612                 :            :                                      "Geneve tunnel must be fully defined");
    3613                 :            :         return 0;
    3614                 :            : }
    3615                 :            : 
    3616                 :            : /**
    3617                 :            :  * Validate Geneve TLV option item.
    3618                 :            :  *
    3619                 :            :  * @param[in] item
    3620                 :            :  *   Item specification.
    3621                 :            :  * @param[in] last_item
    3622                 :            :  *   Previous validated item in the pattern items.
    3623                 :            :  * @param[in] geneve_item
    3624                 :            :  *   Previous GENEVE item specification.
    3625                 :            :  * @param[in] dev
    3626                 :            :  *   Pointer to the rte_eth_dev structure.
    3627                 :            :  * @param[out] error
    3628                 :            :  *   Pointer to error structure.
    3629                 :            :  *
    3630                 :            :  * @return
    3631                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3632                 :            :  */
    3633                 :            : int
    3634                 :          0 : mlx5_flow_validate_item_geneve_opt(const struct rte_flow_item *item,
    3635                 :            :                                    uint64_t last_item,
    3636                 :            :                                    const struct rte_flow_item *geneve_item,
    3637                 :            :                                    struct rte_eth_dev *dev,
    3638                 :            :                                    struct rte_flow_error *error)
    3639                 :            : {
    3640                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3641                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
    3642                 :            :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource;
    3643                 :          0 :         struct mlx5_hca_attr *hca_attr = &sh->cdev->config.hca_attr;
    3644                 :          0 :         uint8_t data_max_supported =
    3645                 :          0 :                         hca_attr->max_geneve_tlv_option_data_len * 4;
    3646                 :            :         const struct rte_flow_item_geneve *geneve_spec;
    3647                 :            :         const struct rte_flow_item_geneve *geneve_mask;
    3648                 :          0 :         const struct rte_flow_item_geneve_opt *spec = item->spec;
    3649                 :          0 :         const struct rte_flow_item_geneve_opt *mask = item->mask;
    3650                 :            :         unsigned int i;
    3651                 :            :         unsigned int data_len;
    3652                 :            :         uint8_t tlv_option_len;
    3653                 :            :         uint16_t optlen_m, optlen_v;
    3654                 :            :         const struct rte_flow_item_geneve_opt full_mask = {
    3655                 :            :                 .option_class = RTE_BE16(0xffff),
    3656                 :            :                 .option_type = 0xff,
    3657                 :            :                 .option_len = 0x1f,
    3658                 :            :         };
    3659                 :            : 
    3660         [ #  # ]:          0 :         if (!mask)
    3661                 :            :                 mask = &rte_flow_item_geneve_opt_mask;
    3662         [ #  # ]:          0 :         if (!spec)
    3663                 :          0 :                 return rte_flow_error_set
    3664                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    3665                 :            :                         "Geneve TLV opt class/type/length must be specified");
    3666         [ #  # ]:          0 :         if ((uint32_t)spec->option_len > MLX5_GENEVE_OPTLEN_MASK)
    3667                 :          0 :                 return rte_flow_error_set
    3668                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    3669                 :            :                         "Geneve TLV opt length exceeds the limit (31)");
    3670                 :            :         /* Check if class type and length masks are full. */
    3671         [ #  # ]:          0 :         if (full_mask.option_class != mask->option_class ||
    3672                 :          0 :             full_mask.option_type != mask->option_type ||
    3673         [ #  # ]:          0 :             full_mask.option_len != (mask->option_len & full_mask.option_len))
    3674                 :          0 :                 return rte_flow_error_set
    3675                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    3676                 :            :                         "Geneve TLV opt class/type/length masks must be full");
    3677                 :            :         /* Check if length is supported */
    3678         [ #  # ]:          0 :         if ((uint32_t)spec->option_len >
    3679                 :            :                         hca_attr->max_geneve_tlv_option_data_len)
    3680                 :          0 :                 return rte_flow_error_set
    3681                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    3682                 :            :                         "Geneve TLV opt length not supported");
    3683         [ #  # ]:          0 :         if (hca_attr->max_geneve_tlv_options > 1)
    3684                 :          0 :                 DRV_LOG(DEBUG,
    3685                 :            :                         "max_geneve_tlv_options supports more than 1 option");
    3686                 :            :         /* Check GENEVE item preceding. */
    3687   [ #  #  #  # ]:          0 :         if (!geneve_item || !(last_item & MLX5_FLOW_LAYER_GENEVE))
    3688                 :          0 :                 return rte_flow_error_set
    3689                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    3690                 :            :                         "Geneve opt item must be preceded with Geneve item");
    3691                 :          0 :         geneve_spec = geneve_item->spec;
    3692         [ #  # ]:          0 :         geneve_mask = geneve_item->mask ? geneve_item->mask :
    3693                 :            :                                           &rte_flow_item_geneve_mask;
    3694                 :            :         /* Check if GENEVE TLV option size doesn't exceed option length */
    3695   [ #  #  #  # ]:          0 :         if (geneve_spec && (geneve_mask->ver_opt_len_o_c_rsvd0 ||
    3696         [ #  # ]:          0 :                             geneve_spec->ver_opt_len_o_c_rsvd0)) {
    3697                 :          0 :                 tlv_option_len = spec->option_len & mask->option_len;
    3698         [ #  # ]:          0 :                 optlen_v = rte_be_to_cpu_16(geneve_spec->ver_opt_len_o_c_rsvd0);
    3699                 :          0 :                 optlen_v = MLX5_GENEVE_OPTLEN_VAL(optlen_v);
    3700         [ #  # ]:          0 :                 optlen_m = rte_be_to_cpu_16(geneve_mask->ver_opt_len_o_c_rsvd0);
    3701                 :          0 :                 optlen_m = MLX5_GENEVE_OPTLEN_VAL(optlen_m);
    3702         [ #  # ]:          0 :                 if ((optlen_v & optlen_m) <= tlv_option_len)
    3703                 :          0 :                         return rte_flow_error_set
    3704                 :            :                                 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    3705                 :            :                                  "GENEVE TLV option length exceeds optlen");
    3706                 :            :         }
    3707                 :            :         /* Check if length is 0 or data is 0. */
    3708   [ #  #  #  # ]:          0 :         if (spec->data == NULL || spec->option_len == 0)
    3709                 :          0 :                 return rte_flow_error_set
    3710                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    3711                 :            :                         "Geneve TLV opt with zero data/length not supported");
    3712                 :            :         /* Check not all data & mask are 0. */
    3713                 :          0 :         data_len = spec->option_len * 4;
    3714         [ #  # ]:          0 :         if (mask->data == NULL) {
    3715         [ #  # ]:          0 :                 for (i = 0; i < data_len; i++)
    3716         [ #  # ]:          0 :                         if (spec->data[i])
    3717                 :            :                                 break;
    3718         [ #  # ]:          0 :                 if (i == data_len)
    3719                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3720                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    3721                 :            :                                 "Can't match on Geneve option data 0");
    3722                 :            :         } else {
    3723         [ #  # ]:          0 :                 for (i = 0; i < data_len; i++)
    3724         [ #  # ]:          0 :                         if (spec->data[i] & mask->data[i])
    3725                 :            :                                 break;
    3726         [ #  # ]:          0 :                 if (i == data_len)
    3727                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3728                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    3729                 :            :                                 "Can't match on Geneve option data and mask 0");
    3730                 :            :                 /* Check data mask supported. */
    3731         [ #  # ]:          0 :                 for (i = data_max_supported; i < data_len ; i++)
    3732         [ #  # ]:          0 :                         if (mask->data[i])
    3733                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    3734                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    3735                 :            :                                         "Data mask is of unsupported size");
    3736                 :            :         }
    3737                 :            :         /* Check GENEVE option is supported in NIC. */
    3738         [ #  # ]:          0 :         if (!hca_attr->geneve_tlv_opt)
    3739                 :          0 :                 return rte_flow_error_set
    3740                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    3741                 :            :                         "Geneve TLV opt not supported");
    3742                 :            :         /* Check if we already have geneve option with different type/class. */
    3743                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
    3744                 :          0 :         geneve_opt_resource = sh->geneve_tlv_option_resource;
    3745         [ #  # ]:          0 :         if (geneve_opt_resource != NULL)
    3746                 :          0 :                 if (geneve_opt_resource->option_class != spec->option_class ||
    3747         [ #  # ]:          0 :                     geneve_opt_resource->option_type != spec->option_type ||
    3748                 :            :                     geneve_opt_resource->length != spec->option_len) {
    3749                 :            :                         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
    3750                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3751                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    3752                 :            :                                 "Only one Geneve TLV option supported");
    3753                 :            :                 }
    3754                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
    3755                 :          0 :         return 0;
    3756                 :            : }
    3757                 :            : 
    3758                 :            : /**
    3759                 :            :  * Validate MPLS item.
    3760                 :            :  *
    3761                 :            :  * @param[in] dev
    3762                 :            :  *   Pointer to the rte_eth_dev structure.
    3763                 :            :  * @param[in] item
    3764                 :            :  *   Item specification.
    3765                 :            :  * @param[in] item_flags
    3766                 :            :  *   Bit-fields that holds the items detected until now.
    3767                 :            :  * @param[in] prev_layer
    3768                 :            :  *   The protocol layer indicated in previous item.
    3769                 :            :  * @param[out] error
    3770                 :            :  *   Pointer to error structure.
    3771                 :            :  *
    3772                 :            :  * @return
    3773                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3774                 :            :  */
    3775                 :            : int
    3776                 :          0 : mlx5_flow_validate_item_mpls(struct rte_eth_dev *dev __rte_unused,
    3777                 :            :                              const struct rte_flow_item *item __rte_unused,
    3778                 :            :                              uint64_t item_flags __rte_unused,
    3779                 :            :                              uint64_t prev_layer __rte_unused,
    3780                 :            :                              struct rte_flow_error *error)
    3781                 :            : {
    3782                 :            : #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT
    3783         [ #  # ]:          0 :         const struct rte_flow_item_mpls hws_nic_mask = {
    3784                 :            :                 .label_tc_s = {0xff, 0xff, 0xff},
    3785                 :            :                 .ttl = 0xff
    3786                 :            :         };
    3787                 :            :         const struct rte_flow_item_mpls *nic_mask = !mlx5_hws_active(dev) ?
    3788         [ #  # ]:          0 :                 &rte_flow_item_mpls_mask : &hws_nic_mask;
    3789                 :          0 :         const struct rte_flow_item_mpls *mask = item->mask;
    3790                 :            :         struct mlx5_priv *priv = dev->data->dev_private;
    3791                 :            :         int ret;
    3792                 :            : 
    3793         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    3794                 :            :                 /* MPLS has HW support in HWS */
    3795         [ #  # ]:          0 :                 if (!priv->sh->dev_cap.mpls_en)
    3796                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3797                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3798                 :            :                                                   item, "MPLS not supported or disabled in firmware configuration.");
    3799                 :            :                 /* MPLS over UDP, GRE is allowed */
    3800         [ #  # ]:          0 :                 if (!(prev_layer & (MLX5_FLOW_LAYER_OUTER_L4_UDP |
    3801                 :            :                                     MLX5_FLOW_LAYER_GRE |
    3802                 :            :                                     MLX5_FLOW_LAYER_GRE_KEY)))
    3803                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3804                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3805                 :            :                                                   item, "protocol filtering not compatible with MPLS layer");
    3806                 :            :                 /* Multi-tunnel isn't allowed but MPLS over GRE is an exception. */
    3807         [ #  # ]:          0 :                 if ((item_flags & MLX5_FLOW_LAYER_TUNNEL) &&
    3808         [ #  # ]:          0 :                     !(item_flags & MLX5_FLOW_LAYER_GRE))
    3809                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3810                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM, item,
    3811                 :            :                                                   "multiple tunnel layers not supported");
    3812                 :            :         }
    3813         [ #  # ]:          0 :         if (!mask)
    3814                 :            :                 mask = nic_mask;
    3815                 :          0 :         ret = mlx5_flow_item_acceptable
    3816                 :            :                 (dev, item, (const uint8_t *)mask,
    3817                 :            :                  (const uint8_t *)nic_mask,
    3818                 :            :                  sizeof(struct rte_flow_item_mpls),
    3819                 :            :                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3820                 :            :         if (ret < 0)
    3821                 :            :                 return ret;
    3822                 :            :         return 0;
    3823                 :            : #else
    3824                 :            :         return rte_flow_error_set(error, ENOTSUP,
    3825                 :            :                                   RTE_FLOW_ERROR_TYPE_ITEM, item,
    3826                 :            :                                   "MPLS is not supported by Verbs, please"
    3827                 :            :                                   " update.");
    3828                 :            : #endif
    3829                 :            : }
    3830                 :            : 
    3831                 :            : /**
    3832                 :            :  * Validate NVGRE item.
    3833                 :            :  *
    3834                 :            :  * @param[in] item
    3835                 :            :  *   Item specification.
    3836                 :            :  * @param[in] item_flags
    3837                 :            :  *   Bit flags to mark detected items.
    3838                 :            :  * @param[in] target_protocol
    3839                 :            :  *   The next protocol in the previous item.
    3840                 :            :  * @param[out] error
    3841                 :            :  *   Pointer to error structure.
    3842                 :            :  *
    3843                 :            :  * @return
    3844                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3845                 :            :  */
    3846                 :            : int
    3847                 :          0 : mlx5_flow_validate_item_nvgre(const struct rte_eth_dev *dev,
    3848                 :            :                               const struct rte_flow_item *item,
    3849                 :            :                               uint64_t item_flags,
    3850                 :            :                               uint8_t target_protocol,
    3851                 :            :                               struct rte_flow_error *error)
    3852                 :            : {
    3853                 :          0 :         const struct rte_flow_item_nvgre *mask = item->mask;
    3854                 :            :         int ret;
    3855                 :            : 
    3856         [ #  # ]:          0 :         const struct rte_flow_item_nvgre hws_nic_mask = {
    3857                 :            :                 .c_k_s_rsvd0_ver = RTE_BE16(0xB000),
    3858                 :            :                 .protocol = RTE_BE16(UINT16_MAX),
    3859                 :            :                 .tni = {0xff, 0xff, 0xff},
    3860                 :            :                 .flow_id = 0xff
    3861                 :            :         };
    3862                 :            :         const struct rte_flow_item_nvgre *nic_mask = !mlx5_hws_active(dev) ?
    3863         [ #  # ]:          0 :                 &rte_flow_item_nvgre_mask : &hws_nic_mask;
    3864                 :            : 
    3865         [ #  # ]:          0 :         if (target_protocol != 0xff && target_protocol != IPPROTO_GRE)
    3866                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3867                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3868                 :            :                                           "protocol filtering not compatible"
    3869                 :            :                                           " with this GRE layer");
    3870         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
    3871                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3872                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3873                 :            :                                           "multiple tunnel layers not"
    3874                 :            :                                           " supported");
    3875         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    3876         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3))
    3877                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3878                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3879                 :            :                                                   item, "L3 Layer is missing");
    3880                 :            :         }
    3881         [ #  # ]:          0 :         if (!mask)
    3882                 :            :                 mask = nic_mask;
    3883                 :          0 :         ret = mlx5_flow_item_acceptable
    3884                 :            :                 (dev, item, (const uint8_t *)mask,
    3885                 :            :                  (const uint8_t *)nic_mask,
    3886                 :            :                  sizeof(struct rte_flow_item_nvgre),
    3887                 :            :                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3888                 :            :         if (ret < 0)
    3889                 :            :                 return ret;
    3890                 :            :         return 0;
    3891                 :            : }
    3892                 :            : 
    3893                 :            : /**
    3894                 :            :  * Validate eCPRI item.
    3895                 :            :  *
    3896                 :            :  * @param[in] item
    3897                 :            :  *   Item specification.
    3898                 :            :  * @param[in] item_flags
    3899                 :            :  *   Bit-fields that holds the items detected until now.
    3900                 :            :  * @param[in] last_item
    3901                 :            :  *   Previous validated item in the pattern items.
    3902                 :            :  * @param[in] ether_type
    3903                 :            :  *   Type in the ethernet layer header (including dot1q).
    3904                 :            :  * @param[in] acc_mask
    3905                 :            :  *   Acceptable mask, if NULL default internal default mask
    3906                 :            :  *   will be used to check whether item fields are supported.
    3907                 :            :  * @param[out] error
    3908                 :            :  *   Pointer to error structure.
    3909                 :            :  *
    3910                 :            :  * @return
    3911                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3912                 :            :  */
    3913                 :            : int
    3914                 :          0 : mlx5_flow_validate_item_ecpri(const struct rte_eth_dev *dev,
    3915                 :            :                               const struct rte_flow_item *item,
    3916                 :            :                               uint64_t item_flags,
    3917                 :            :                               uint64_t last_item,
    3918                 :            :                               uint16_t ether_type,
    3919                 :            :                               const struct rte_flow_item_ecpri *acc_mask,
    3920                 :            :                               struct rte_flow_error *error)
    3921                 :            : {
    3922                 :          0 :         const struct rte_flow_item_ecpri *mask = item->mask;
    3923                 :          0 :         const struct rte_flow_item_ecpri nic_mask = {
    3924                 :            :                 .hdr = {
    3925                 :            :                         .common = {
    3926                 :            :                                 .u32 =
    3927                 :            :                                 RTE_BE32(((const struct rte_ecpri_common_hdr) {
    3928                 :            :                                         .type = 0xFF,
    3929                 :            :                                         }).u32),
    3930                 :            :                         },
    3931                 :            :                         .dummy[0] = 0xFFFFFFFF,
    3932                 :            :                 },
    3933                 :            :         };
    3934                 :            :         const uint64_t outer_l2_vlan = (MLX5_FLOW_LAYER_OUTER_L2 |
    3935                 :            :                                         MLX5_FLOW_LAYER_OUTER_VLAN);
    3936                 :            :         struct rte_flow_item_ecpri mask_lo;
    3937                 :            : 
    3938   [ #  #  #  # ]:          0 :         if (!(last_item & outer_l2_vlan) &&
    3939                 :            :             last_item != MLX5_FLOW_LAYER_OUTER_L4_UDP)
    3940                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3941                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3942                 :            :                                           "eCPRI can only follow L2/VLAN layer or UDP layer");
    3943         [ #  # ]:          0 :         if ((last_item & outer_l2_vlan) && ether_type &&
    3944         [ #  # ]:          0 :             ether_type != RTE_ETHER_TYPE_ECPRI)
    3945                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3946                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3947                 :            :                                           "eCPRI cannot follow L2/VLAN layer which ether type is not 0xAEFE");
    3948         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
    3949                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3950                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3951                 :            :                                           "eCPRI with tunnel is not supported right now");
    3952         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_OUTER_L3)
    3953                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3954                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3955                 :            :                                           "multiple L3 layers not supported");
    3956         [ #  # ]:          0 :         else if (item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP)
    3957                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3958                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3959                 :            :                                           "eCPRI cannot coexist with a TCP layer");
    3960                 :            :         /* In specification, eCPRI could be over UDP layer. */
    3961         [ #  # ]:          0 :         else if (item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)
    3962                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3963                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3964                 :            :                                           "eCPRI over UDP layer is not yet supported right now");
    3965                 :            :         /* Mask for type field in common header could be zero. */
    3966         [ #  # ]:          0 :         if (!mask)
    3967                 :            :                 mask = &rte_flow_item_ecpri_mask;
    3968         [ #  # ]:          0 :         mask_lo.hdr.common.u32 = rte_be_to_cpu_32(mask->hdr.common.u32);
    3969                 :            :         /* Input mask is in big-endian format. */
    3970         [ #  # ]:          0 :         if (mask_lo.hdr.common.type != 0 && mask_lo.hdr.common.type != 0xff)
    3971                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3972                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,
    3973                 :            :                                           "partial mask is not supported for protocol");
    3974   [ #  #  #  # ]:          0 :         else if (mask_lo.hdr.common.type == 0 && mask->hdr.dummy[0] != 0)
    3975                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3976                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,
    3977                 :            :                                           "message header mask must be after a type mask");
    3978         [ #  # ]:          0 :         return mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    3979                 :            :                                          acc_mask ? (const uint8_t *)acc_mask
    3980                 :            :                                                   : (const uint8_t *)&nic_mask,
    3981                 :            :                                          sizeof(struct rte_flow_item_ecpri),
    3982                 :            :                                          MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3983                 :            : }
    3984                 :            : 
    3985                 :            : /**
    3986                 :            :  * Validate the NSH item.
    3987                 :            :  *
    3988                 :            :  * @param[in] dev
    3989                 :            :  *   Pointer to Ethernet device on which flow rule is being created on.
    3990                 :            :  * @param[out] error
    3991                 :            :  *   Pointer to error structure.
    3992                 :            :  *
    3993                 :            :  * @return
    3994                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3995                 :            :  */
    3996                 :            : int
    3997                 :          0 : mlx5_flow_validate_item_nsh(struct rte_eth_dev *dev,
    3998                 :            :                             const struct rte_flow_item *item,
    3999                 :            :                             struct rte_flow_error *error)
    4000                 :            : {
    4001                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4002                 :            : 
    4003         [ #  # ]:          0 :         if (item->mask) {
    4004                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4005                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    4006                 :            :                                           "NSH fields matching is not supported");
    4007                 :            :         }
    4008                 :            : 
    4009         [ #  # ]:          0 :         if (!priv->sh->config.dv_flow_en) {
    4010                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4011                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4012                 :            :                                           NULL, "NSH support requires DV flow interface");
    4013                 :            :         }
    4014                 :            : 
    4015         [ #  # ]:          0 :         if (!priv->sh->cdev->config.hca_attr.tunnel_stateless_vxlan_gpe_nsh) {
    4016                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4017                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    4018                 :            :                                           "Current FW does not support matching on NSH");
    4019                 :            :         }
    4020                 :            : 
    4021                 :            :         return 0;
    4022                 :            : }
    4023                 :            : 
    4024                 :            : static uintptr_t
    4025                 :          0 : flow_null_list_create(struct rte_eth_dev *dev __rte_unused,
    4026                 :            :                       enum mlx5_flow_type type __rte_unused,
    4027                 :            :                       const struct rte_flow_attr *attr __rte_unused,
    4028                 :            :                       const struct rte_flow_item items[] __rte_unused,
    4029                 :            :                       const struct rte_flow_action actions[] __rte_unused,
    4030                 :            :                       bool external __rte_unused,
    4031                 :            :                       struct rte_flow_error *error)
    4032                 :            : {
    4033                 :          0 :         rte_flow_error_set(error, ENOTSUP,
    4034                 :            :                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL);
    4035                 :          0 :         return 0;
    4036                 :            : }
    4037                 :            : 
    4038                 :            : static int
    4039                 :          0 : flow_null_validate(struct rte_eth_dev *dev __rte_unused,
    4040                 :            :                    const struct rte_flow_attr *attr __rte_unused,
    4041                 :            :                    const struct rte_flow_item items[] __rte_unused,
    4042                 :            :                    const struct rte_flow_action actions[] __rte_unused,
    4043                 :            :                    bool external __rte_unused,
    4044                 :            :                    int hairpin __rte_unused,
    4045                 :            :                    struct rte_flow_error *error)
    4046                 :            : {
    4047                 :          0 :         return rte_flow_error_set(error, ENOTSUP,
    4048                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL);
    4049                 :            : }
    4050                 :            : 
    4051                 :            : static struct mlx5_flow *
    4052                 :          0 : flow_null_prepare(struct rte_eth_dev *dev __rte_unused,
    4053                 :            :                   const struct rte_flow_attr *attr __rte_unused,
    4054                 :            :                   const struct rte_flow_item items[] __rte_unused,
    4055                 :            :                   const struct rte_flow_action actions[] __rte_unused,
    4056                 :            :                   struct rte_flow_error *error)
    4057                 :            : {
    4058                 :          0 :         rte_flow_error_set(error, ENOTSUP,
    4059                 :            :                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL);
    4060                 :          0 :         return NULL;
    4061                 :            : }
    4062                 :            : 
    4063                 :            : static int
    4064                 :          0 : flow_null_translate(struct rte_eth_dev *dev __rte_unused,
    4065                 :            :                     struct mlx5_flow *dev_flow __rte_unused,
    4066                 :            :                     const struct rte_flow_attr *attr __rte_unused,
    4067                 :            :                     const struct rte_flow_item items[] __rte_unused,
    4068                 :            :                     const struct rte_flow_action actions[] __rte_unused,
    4069                 :            :                     struct rte_flow_error *error)
    4070                 :            : {
    4071                 :          0 :         return rte_flow_error_set(error, ENOTSUP,
    4072                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL);
    4073                 :            : }
    4074                 :            : 
    4075                 :            : static int
    4076                 :          0 : flow_null_apply(struct rte_eth_dev *dev __rte_unused,
    4077                 :            :                 struct rte_flow *flow __rte_unused,
    4078                 :            :                 struct rte_flow_error *error)
    4079                 :            : {
    4080                 :          0 :         return rte_flow_error_set(error, ENOTSUP,
    4081                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL);
    4082                 :            : }
    4083                 :            : 
    4084                 :            : static void
    4085                 :          0 : flow_null_remove(struct rte_eth_dev *dev __rte_unused,
    4086                 :            :                  struct rte_flow *flow __rte_unused)
    4087                 :            : {
    4088                 :          0 : }
    4089                 :            : 
    4090                 :            : static void
    4091                 :          0 : flow_null_destroy(struct rte_eth_dev *dev __rte_unused,
    4092                 :            :                   struct rte_flow *flow __rte_unused)
    4093                 :            : {
    4094                 :          0 : }
    4095                 :            : 
    4096                 :            : static int
    4097                 :          0 : flow_null_query(struct rte_eth_dev *dev __rte_unused,
    4098                 :            :                 struct rte_flow *flow __rte_unused,
    4099                 :            :                 const struct rte_flow_action *actions __rte_unused,
    4100                 :            :                 void *data __rte_unused,
    4101                 :            :                 struct rte_flow_error *error)
    4102                 :            : {
    4103                 :          0 :         return rte_flow_error_set(error, ENOTSUP,
    4104                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL);
    4105                 :            : }
    4106                 :            : 
    4107                 :            : static int
    4108                 :          0 : flow_null_sync_domain(struct rte_eth_dev *dev __rte_unused,
    4109                 :            :                       uint32_t domains __rte_unused,
    4110                 :            :                       uint32_t flags __rte_unused)
    4111                 :            : {
    4112                 :          0 :         return 0;
    4113                 :            : }
    4114                 :            : 
    4115                 :            : int
    4116                 :          0 : flow_null_get_aged_flows(struct rte_eth_dev *dev,
    4117                 :            :                     void **context __rte_unused,
    4118                 :            :                     uint32_t nb_contexts __rte_unused,
    4119                 :            :                     struct rte_flow_error *error __rte_unused)
    4120                 :            : {
    4121                 :          0 :         DRV_LOG(ERR, "port %u get aged flows is not supported.",
    4122                 :            :                 dev->data->port_id);
    4123                 :          0 :         return -ENOTSUP;
    4124                 :            : }
    4125                 :            : 
    4126                 :            : uint32_t
    4127                 :          0 : flow_null_counter_allocate(struct rte_eth_dev *dev)
    4128                 :            : {
    4129                 :          0 :         DRV_LOG(ERR, "port %u counter allocate is not supported.",
    4130                 :            :                 dev->data->port_id);
    4131                 :          0 :         return 0;
    4132                 :            : }
    4133                 :            : 
    4134                 :            : void
    4135                 :          0 : flow_null_counter_free(struct rte_eth_dev *dev,
    4136                 :            :                         uint32_t counter __rte_unused)
    4137                 :            : {
    4138                 :          0 :         DRV_LOG(ERR, "port %u counter free is not supported.",
    4139                 :            :                  dev->data->port_id);
    4140                 :          0 : }
    4141                 :            : 
    4142                 :            : int
    4143                 :          0 : flow_null_counter_query(struct rte_eth_dev *dev,
    4144                 :            :                         uint32_t counter __rte_unused,
    4145                 :            :                         bool clear __rte_unused,
    4146                 :            :                         uint64_t *pkts __rte_unused,
    4147                 :            :                         uint64_t *bytes __rte_unused,
    4148                 :            :                         void **action __rte_unused)
    4149                 :            : {
    4150                 :          0 :         DRV_LOG(ERR, "port %u counter query is not supported.",
    4151                 :            :                  dev->data->port_id);
    4152                 :          0 :         return -ENOTSUP;
    4153                 :            : }
    4154                 :            : 
    4155                 :            : /* Void driver to protect from null pointer reference. */
    4156                 :            : const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops = {
    4157                 :            :         .list_create = flow_null_list_create,
    4158                 :            :         .validate = flow_null_validate,
    4159                 :            :         .prepare = flow_null_prepare,
    4160                 :            :         .translate = flow_null_translate,
    4161                 :            :         .apply = flow_null_apply,
    4162                 :            :         .remove = flow_null_remove,
    4163                 :            :         .destroy = flow_null_destroy,
    4164                 :            :         .query = flow_null_query,
    4165                 :            :         .sync_domain = flow_null_sync_domain,
    4166                 :            :         .get_aged_flows = flow_null_get_aged_flows,
    4167                 :            :         .counter_alloc = flow_null_counter_allocate,
    4168                 :            :         .counter_free = flow_null_counter_free,
    4169                 :            :         .counter_query = flow_null_counter_query
    4170                 :            : };
    4171                 :            : 
    4172                 :            : /**
    4173                 :            :  * Select flow driver type according to flow attributes and device
    4174                 :            :  * configuration.
    4175                 :            :  *
    4176                 :            :  * @param[in] dev
    4177                 :            :  *   Pointer to the dev structure.
    4178                 :            :  * @param[in] attr
    4179                 :            :  *   Pointer to the flow attributes.
    4180                 :            :  *
    4181                 :            :  * @return
    4182                 :            :  *   flow driver type, MLX5_FLOW_TYPE_MAX otherwise.
    4183                 :            :  */
    4184                 :            : static enum mlx5_flow_drv_type
    4185                 :          0 : flow_get_drv_type(struct rte_eth_dev *dev, const struct rte_flow_attr *attr)
    4186                 :            : {
    4187                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4188                 :            :         /* The OS can determine first a specific flow type (DV, VERBS) */
    4189                 :            :         enum mlx5_flow_drv_type type = mlx5_flow_os_get_type();
    4190                 :            : 
    4191                 :            :         if (type != MLX5_FLOW_TYPE_MAX)
    4192                 :            :                 return type;
    4193                 :            :         /*
    4194                 :            :          * Currently when dv_flow_en == 2, only HW steering engine is
    4195                 :            :          * supported. New engines can also be chosen here if ready.
    4196                 :            :          */
    4197         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
    4198                 :            :                 return MLX5_FLOW_TYPE_HW;
    4199         [ #  # ]:          0 :         if (!attr)
    4200                 :            :                 return MLX5_FLOW_TYPE_MIN;
    4201                 :            :         /* If no OS specific type - continue with DV/VERBS selection */
    4202   [ #  #  #  # ]:          0 :         if (attr->transfer && priv->sh->config.dv_esw_en)
    4203                 :            :                 type = MLX5_FLOW_TYPE_DV;
    4204         [ #  # ]:          0 :         if (!attr->transfer)
    4205   [ #  #  #  #  :          0 :                 type = priv->sh->config.dv_flow_en ? MLX5_FLOW_TYPE_DV :
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    4206                 :            :                                                      MLX5_FLOW_TYPE_VERBS;
    4207                 :            :         return type;
    4208                 :            : }
    4209                 :            : 
    4210                 :            : #define flow_get_drv_ops(type) flow_drv_ops[type]
    4211                 :            : 
    4212                 :            : /**
    4213                 :            :  * Flow driver validation API. This abstracts calling driver specific functions.
    4214                 :            :  * The type of flow driver is determined according to flow attributes.
    4215                 :            :  *
    4216                 :            :  * @param[in] dev
    4217                 :            :  *   Pointer to the dev structure.
    4218                 :            :  * @param[in] attr
    4219                 :            :  *   Pointer to the flow attributes.
    4220                 :            :  * @param[in] items
    4221                 :            :  *   Pointer to the list of items.
    4222                 :            :  * @param[in] actions
    4223                 :            :  *   Pointer to the list of actions.
    4224                 :            :  * @param[in] external
    4225                 :            :  *   This flow rule is created by request external to PMD.
    4226                 :            :  * @param[in] hairpin
    4227                 :            :  *   Number of hairpin TX actions, 0 means classic flow.
    4228                 :            :  * @param[out] error
    4229                 :            :  *   Pointer to the error structure.
    4230                 :            :  *
    4231                 :            :  * @return
    4232                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4233                 :            :  */
    4234                 :            : static inline int
    4235                 :          0 : flow_drv_validate(struct rte_eth_dev *dev,
    4236                 :            :                   const struct rte_flow_attr *attr,
    4237                 :            :                   const struct rte_flow_item items[],
    4238                 :            :                   const struct rte_flow_action actions[],
    4239                 :            :                   bool external, int hairpin, struct rte_flow_error *error)
    4240                 :            : {
    4241                 :            :         const struct mlx5_flow_driver_ops *fops;
    4242                 :          0 :         enum mlx5_flow_drv_type type = flow_get_drv_type(dev, attr);
    4243                 :            : 
    4244                 :          0 :         fops = flow_get_drv_ops(type);
    4245                 :          0 :         return fops->validate(dev, attr, items, actions, external,
    4246                 :            :                               hairpin, error);
    4247                 :            : }
    4248                 :            : 
    4249                 :            : /**
    4250                 :            :  * Flow driver preparation API. This abstracts calling driver specific
    4251                 :            :  * functions. Parent flow (rte_flow) should have driver type (drv_type). It
    4252                 :            :  * calculates the size of memory required for device flow, allocates the memory,
    4253                 :            :  * initializes the device flow and returns the pointer.
    4254                 :            :  *
    4255                 :            :  * @note
    4256                 :            :  *   This function initializes device flow structure such as dv or verbs in
    4257                 :            :  *   struct mlx5_flow. However, it is caller's responsibility to initialize the
    4258                 :            :  *   rest. For example, adding returning device flow to flow->dev_flow list and
    4259                 :            :  *   setting backward reference to the flow should be done out of this function.
    4260                 :            :  *   layers field is not filled either.
    4261                 :            :  *
    4262                 :            :  * @param[in] dev
    4263                 :            :  *   Pointer to the dev structure.
    4264                 :            :  * @param[in] attr
    4265                 :            :  *   Pointer to the flow attributes.
    4266                 :            :  * @param[in] items
    4267                 :            :  *   Pointer to the list of items.
    4268                 :            :  * @param[in] actions
    4269                 :            :  *   Pointer to the list of actions.
    4270                 :            :  * @param[in] flow_idx
    4271                 :            :  *   This memory pool index to the flow.
    4272                 :            :  * @param[out] error
    4273                 :            :  *   Pointer to the error structure.
    4274                 :            :  *
    4275                 :            :  * @return
    4276                 :            :  *   Pointer to device flow on success, otherwise NULL and rte_errno is set.
    4277                 :            :  */
    4278                 :            : static inline struct mlx5_flow *
    4279                 :            : flow_drv_prepare(struct rte_eth_dev *dev,
    4280                 :            :                  const struct rte_flow *flow,
    4281                 :            :                  const struct rte_flow_attr *attr,
    4282                 :            :                  const struct rte_flow_item items[],
    4283                 :            :                  const struct rte_flow_action actions[],
    4284                 :            :                  uint32_t flow_idx,
    4285                 :            :                  struct rte_flow_error *error)
    4286                 :            : {
    4287                 :            :         const struct mlx5_flow_driver_ops *fops;
    4288                 :          0 :         enum mlx5_flow_drv_type type = flow->drv_type;
    4289                 :            :         struct mlx5_flow *mlx5_flow = NULL;
    4290                 :            : 
    4291                 :            :         MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
    4292                 :          0 :         fops = flow_get_drv_ops(type);
    4293                 :          0 :         mlx5_flow = fops->prepare(dev, attr, items, actions, error);
    4294   [ #  #  #  #  :          0 :         if (mlx5_flow)
                   #  # ]
    4295                 :          0 :                 mlx5_flow->flow_idx = flow_idx;
    4296                 :            :         return mlx5_flow;
    4297                 :            : }
    4298                 :            : 
    4299                 :            : /**
    4300                 :            :  * Flow driver translation API. This abstracts calling driver specific
    4301                 :            :  * functions. Parent flow (rte_flow) should have driver type (drv_type). It
    4302                 :            :  * translates a generic flow into a driver flow. flow_drv_prepare() must
    4303                 :            :  * precede.
    4304                 :            :  *
    4305                 :            :  * @note
    4306                 :            :  *   dev_flow->layers could be filled as a result of parsing during translation
    4307                 :            :  *   if needed by flow_drv_apply(). dev_flow->flow->actions can also be filled
    4308                 :            :  *   if necessary. As a flow can have multiple dev_flows by RSS flow expansion,
    4309                 :            :  *   flow->actions could be overwritten even though all the expanded dev_flows
    4310                 :            :  *   have the same actions.
    4311                 :            :  *
    4312                 :            :  * @param[in] dev
    4313                 :            :  *   Pointer to the rte dev structure.
    4314                 :            :  * @param[in, out] dev_flow
    4315                 :            :  *   Pointer to the mlx5 flow.
    4316                 :            :  * @param[in] attr
    4317                 :            :  *   Pointer to the flow attributes.
    4318                 :            :  * @param[in] items
    4319                 :            :  *   Pointer to the list of items.
    4320                 :            :  * @param[in] actions
    4321                 :            :  *   Pointer to the list of actions.
    4322                 :            :  * @param[out] error
    4323                 :            :  *   Pointer to the error structure.
    4324                 :            :  *
    4325                 :            :  * @return
    4326                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4327                 :            :  */
    4328                 :            : static inline int
    4329                 :            : flow_drv_translate(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow,
    4330                 :            :                    const struct rte_flow_attr *attr,
    4331                 :            :                    const struct rte_flow_item items[],
    4332                 :            :                    const struct rte_flow_action actions[],
    4333                 :            :                    struct rte_flow_error *error)
    4334                 :            : {
    4335                 :            :         const struct mlx5_flow_driver_ops *fops;
    4336                 :          0 :         enum mlx5_flow_drv_type type = dev_flow->flow->drv_type;
    4337                 :            : 
    4338                 :            :         MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
    4339                 :          0 :         fops = flow_get_drv_ops(type);
    4340                 :          0 :         return fops->translate(dev, dev_flow, attr, items, actions, error);
    4341                 :            : }
    4342                 :            : 
    4343                 :            : /**
    4344                 :            :  * Flow driver apply API. This abstracts calling driver specific functions.
    4345                 :            :  * Parent flow (rte_flow) should have driver type (drv_type). It applies
    4346                 :            :  * translated driver flows on to device. flow_drv_translate() must precede.
    4347                 :            :  *
    4348                 :            :  * @param[in] dev
    4349                 :            :  *   Pointer to Ethernet device structure.
    4350                 :            :  * @param[in, out] flow
    4351                 :            :  *   Pointer to flow structure.
    4352                 :            :  * @param[out] error
    4353                 :            :  *   Pointer to error structure.
    4354                 :            :  *
    4355                 :            :  * @return
    4356                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4357                 :            :  */
    4358                 :            : static inline int
    4359                 :            : flow_drv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
    4360                 :            :                struct rte_flow_error *error)
    4361                 :            : {
    4362                 :            :         const struct mlx5_flow_driver_ops *fops;
    4363                 :          0 :         enum mlx5_flow_drv_type type = flow->drv_type;
    4364                 :            : 
    4365                 :            :         MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
    4366                 :          0 :         fops = flow_get_drv_ops(type);
    4367                 :          0 :         return fops->apply(dev, flow, error);
    4368                 :            : }
    4369                 :            : 
    4370                 :            : /**
    4371                 :            :  * Flow driver destroy API. This abstracts calling driver specific functions.
    4372                 :            :  * Parent flow (rte_flow) should have driver type (drv_type). It removes a flow
    4373                 :            :  * on device and releases resources of the flow.
    4374                 :            :  *
    4375                 :            :  * @param[in] dev
    4376                 :            :  *   Pointer to Ethernet device.
    4377                 :            :  * @param[in, out] flow
    4378                 :            :  *   Pointer to flow structure.
    4379                 :            :  */
    4380                 :            : static inline void
    4381                 :            : flow_drv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
    4382                 :            : {
    4383                 :            :         const struct mlx5_flow_driver_ops *fops;
    4384                 :          0 :         enum mlx5_flow_drv_type type = flow->drv_type;
    4385                 :            : 
    4386                 :            :         MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
    4387                 :          0 :         fops = flow_get_drv_ops(type);
    4388                 :          0 :         fops->destroy(dev, flow);
    4389                 :            : }
    4390                 :            : 
    4391                 :            : /**
    4392                 :            :  * Flow driver find RSS policy tbl API. This abstracts calling driver
    4393                 :            :  * specific functions. Parent flow (rte_flow) should have driver
    4394                 :            :  * type (drv_type). It will find the RSS policy table that has the rss_desc.
    4395                 :            :  *
    4396                 :            :  * @param[in] dev
    4397                 :            :  *   Pointer to Ethernet device.
    4398                 :            :  * @param[in, out] flow
    4399                 :            :  *   Pointer to flow structure.
    4400                 :            :  * @param[in] policy
    4401                 :            :  *   Pointer to meter policy table.
    4402                 :            :  * @param[in] rss_desc
    4403                 :            :  *   Pointer to rss_desc
    4404                 :            :  */
    4405                 :            : static struct mlx5_flow_meter_sub_policy *
    4406                 :            : flow_drv_meter_sub_policy_rss_prepare(struct rte_eth_dev *dev,
    4407                 :            :                 struct rte_flow *flow,
    4408                 :            :                 struct mlx5_flow_meter_policy *policy,
    4409                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS])
    4410                 :            : {
    4411                 :            :         const struct mlx5_flow_driver_ops *fops;
    4412                 :          0 :         enum mlx5_flow_drv_type type = flow->drv_type;
    4413                 :            : 
    4414                 :            :         MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
    4415                 :          0 :         fops = flow_get_drv_ops(type);
    4416                 :          0 :         return fops->meter_sub_policy_rss_prepare(dev, policy, rss_desc);
    4417                 :            : }
    4418                 :            : 
    4419                 :            : /**
    4420                 :            :  * Flow driver color tag rule API. This abstracts calling driver
    4421                 :            :  * specific functions. Parent flow (rte_flow) should have driver
    4422                 :            :  * type (drv_type). It will create the color tag rules in hierarchy meter.
    4423                 :            :  *
    4424                 :            :  * @param[in] dev
    4425                 :            :  *   Pointer to Ethernet device.
    4426                 :            :  * @param[in, out] flow
    4427                 :            :  *   Pointer to flow structure.
    4428                 :            :  * @param[in] fm
    4429                 :            :  *   Pointer to flow meter structure.
    4430                 :            :  * @param[in] src_port
    4431                 :            :  *   The src port this extra rule should use.
    4432                 :            :  * @param[in] item
    4433                 :            :  *   The src port id match item.
    4434                 :            :  * @param[out] error
    4435                 :            :  *   Pointer to error structure.
    4436                 :            :  */
    4437                 :            : static int
    4438                 :            : flow_drv_mtr_hierarchy_rule_create(struct rte_eth_dev *dev,
    4439                 :            :                 struct rte_flow *flow,
    4440                 :            :                 struct mlx5_flow_meter_info *fm,
    4441                 :            :                 int32_t src_port,
    4442                 :            :                 const struct rte_flow_item *item,
    4443                 :            :                 struct rte_flow_error *error)
    4444                 :            : {
    4445                 :            :         const struct mlx5_flow_driver_ops *fops;
    4446                 :          0 :         enum mlx5_flow_drv_type type = flow->drv_type;
    4447                 :            : 
    4448                 :            :         MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
    4449                 :          0 :         fops = flow_get_drv_ops(type);
    4450                 :          0 :         return fops->meter_hierarchy_rule_create(dev, fm,
    4451                 :            :                                                 src_port, item, error);
    4452                 :            : }
    4453                 :            : 
    4454                 :            : /**
    4455                 :            :  * Get RSS action from the action list.
    4456                 :            :  *
    4457                 :            :  * @param[in] dev
    4458                 :            :  *   Pointer to Ethernet device.
    4459                 :            :  * @param[in] actions
    4460                 :            :  *   Pointer to the list of actions.
    4461                 :            :  * @param[in] flow
    4462                 :            :  *   Parent flow structure pointer.
    4463                 :            :  *
    4464                 :            :  * @return
    4465                 :            :  *   Pointer to the RSS action if exist, else return NULL.
    4466                 :            :  */
    4467                 :            : static const struct rte_flow_action_rss*
    4468                 :          0 : flow_get_rss_action(struct rte_eth_dev *dev,
    4469                 :            :                     const struct rte_flow_action actions[])
    4470                 :            : {
    4471                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4472                 :            :         const struct rte_flow_action_rss *rss = NULL;
    4473                 :            :         struct mlx5_meter_policy_action_container *acg;
    4474                 :            :         struct mlx5_meter_policy_action_container *acy;
    4475                 :            : 
    4476         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    4477   [ #  #  #  # ]:          0 :                 switch (actions->type) {
    4478                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    4479                 :          0 :                         rss = actions->conf;
    4480                 :          0 :                         break;
    4481                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
    4482                 :            :                 {
    4483                 :          0 :                         const struct rte_flow_action_sample *sample =
    4484                 :            :                                                                 actions->conf;
    4485                 :          0 :                         const struct rte_flow_action *act = sample->actions;
    4486         [ #  # ]:          0 :                         for (; act->type != RTE_FLOW_ACTION_TYPE_END; act++)
    4487         [ #  # ]:          0 :                                 if (act->type == RTE_FLOW_ACTION_TYPE_RSS)
    4488                 :          0 :                                         rss = act->conf;
    4489                 :            :                         break;
    4490                 :            :                 }
    4491                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    4492                 :            :                 {
    4493                 :            :                         uint32_t mtr_idx;
    4494                 :            :                         struct mlx5_flow_meter_info *fm;
    4495                 :            :                         struct mlx5_flow_meter_policy *policy;
    4496                 :          0 :                         const struct rte_flow_action_meter *mtr = actions->conf;
    4497                 :            : 
    4498                 :          0 :                         fm = mlx5_flow_meter_find(priv, mtr->mtr_id, &mtr_idx);
    4499   [ #  #  #  # ]:          0 :                         if (fm && !fm->def_policy) {
    4500                 :          0 :                                 policy = mlx5_flow_meter_policy_find(dev,
    4501                 :            :                                                 fm->policy_id, NULL);
    4502                 :            :                                 MLX5_ASSERT(policy);
    4503         [ #  # ]:          0 :                                 if (policy->is_hierarchy) {
    4504                 :            :                                         policy =
    4505                 :          0 :                                 mlx5_flow_meter_hierarchy_get_final_policy(dev,
    4506                 :            :                                                                         policy);
    4507         [ #  # ]:          0 :                                         if (!policy)
    4508                 :          0 :                                                 return NULL;
    4509                 :            :                                 }
    4510         [ #  # ]:          0 :                                 if (policy->is_rss) {
    4511                 :            :                                         acg =
    4512                 :            :                                         &policy->act_cnt[RTE_COLOR_GREEN];
    4513                 :            :                                         acy =
    4514                 :            :                                         &policy->act_cnt[RTE_COLOR_YELLOW];
    4515         [ #  # ]:          0 :                                         if (acg->fate_action ==
    4516                 :            :                                             MLX5_FLOW_FATE_SHARED_RSS)
    4517                 :          0 :                                                 rss = acg->rss->conf;
    4518         [ #  # ]:          0 :                                         else if (acy->fate_action ==
    4519                 :            :                                                  MLX5_FLOW_FATE_SHARED_RSS)
    4520                 :          0 :                                                 rss = acy->rss->conf;
    4521                 :            :                                 }
    4522                 :            :                         }
    4523                 :          0 :                         break;
    4524                 :            :                 }
    4525                 :            :                 default:
    4526                 :            :                         break;
    4527                 :            :                 }
    4528                 :            :         }
    4529                 :            :         return rss;
    4530                 :            : }
    4531                 :            : 
    4532                 :            : /**
    4533                 :            :  * Get ASO age action by index.
    4534                 :            :  *
    4535                 :            :  * @param[in] dev
    4536                 :            :  *   Pointer to the Ethernet device structure.
    4537                 :            :  * @param[in] age_idx
    4538                 :            :  *   Index to the ASO age action.
    4539                 :            :  *
    4540                 :            :  * @return
    4541                 :            :  *   The specified ASO age action.
    4542                 :            :  */
    4543                 :            : struct mlx5_aso_age_action*
    4544                 :          0 : flow_aso_age_get_by_idx(struct rte_eth_dev *dev, uint32_t age_idx)
    4545                 :            : {
    4546                 :          0 :         uint16_t pool_idx = age_idx & UINT16_MAX;
    4547                 :          0 :         uint16_t offset = (age_idx >> 16) & UINT16_MAX;
    4548                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4549                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
    4550                 :            :         struct mlx5_aso_age_pool *pool;
    4551                 :            : 
    4552                 :          0 :         rte_rwlock_read_lock(&mng->resize_rwl);
    4553                 :          0 :         pool = mng->pools[pool_idx];
    4554                 :            :         rte_rwlock_read_unlock(&mng->resize_rwl);
    4555                 :          0 :         return &pool->actions[offset - 1];
    4556                 :            : }
    4557                 :            : 
    4558                 :            : /* maps indirect action to translated direct in some actions array */
    4559                 :            : struct mlx5_translated_action_handle {
    4560                 :            :         struct rte_flow_action_handle *action; /**< Indirect action handle. */
    4561                 :            :         int index; /**< Index in related array of rte_flow_action. */
    4562                 :            : };
    4563                 :            : 
    4564                 :            : /**
    4565                 :            :  * Translates actions of type RTE_FLOW_ACTION_TYPE_INDIRECT to related
    4566                 :            :  * direct action if translation possible.
    4567                 :            :  * This functionality used to run same execution path for both direct and
    4568                 :            :  * indirect actions on flow create. All necessary preparations for indirect
    4569                 :            :  * action handling should be performed on *handle* actions list returned
    4570                 :            :  * from this call.
    4571                 :            :  *
    4572                 :            :  * @param[in] dev
    4573                 :            :  *   Pointer to Ethernet device.
    4574                 :            :  * @param[in] actions
    4575                 :            :  *   List of actions to translate.
    4576                 :            :  * @param[out] handle
    4577                 :            :  *   List to store translated indirect action object handles.
    4578                 :            :  * @param[in, out] indir_n
    4579                 :            :  *   Size of *handle* array. On return should be updated with number of
    4580                 :            :  *   indirect actions retrieved from the *actions* list.
    4581                 :            :  * @param[out] translated_actions
    4582                 :            :  *   List of actions where all indirect actions were translated to direct
    4583                 :            :  *   if possible. NULL if no translation took place.
    4584                 :            :  * @param[out] error
    4585                 :            :  *   Pointer to the error structure.
    4586                 :            :  *
    4587                 :            :  * @return
    4588                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4589                 :            :  */
    4590                 :            : static int
    4591                 :          0 : flow_action_handles_translate(struct rte_eth_dev *dev,
    4592                 :            :                               const struct rte_flow_action actions[],
    4593                 :            :                               struct mlx5_translated_action_handle *handle,
    4594                 :            :                               int *indir_n,
    4595                 :            :                               struct rte_flow_action **translated_actions,
    4596                 :            :                               struct rte_flow_error *error)
    4597                 :            : {
    4598                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4599                 :            :         struct rte_flow_action *translated = NULL;
    4600                 :            :         size_t actions_size;
    4601                 :            :         int n;
    4602                 :            :         int copied_n = 0;
    4603                 :            :         struct mlx5_translated_action_handle *handle_end = NULL;
    4604                 :            : 
    4605         [ #  # ]:          0 :         for (n = 0; actions[n].type != RTE_FLOW_ACTION_TYPE_END; n++) {
    4606         [ #  # ]:          0 :                 if (actions[n].type != RTE_FLOW_ACTION_TYPE_INDIRECT)
    4607                 :          0 :                         continue;
    4608         [ #  # ]:          0 :                 if (copied_n == *indir_n) {
    4609                 :          0 :                         return rte_flow_error_set
    4610                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
    4611                 :            :                                  NULL, "too many shared actions");
    4612                 :            :                 }
    4613         [ #  # ]:          0 :                 rte_memcpy(&handle[copied_n].action, &actions[n].conf,
    4614                 :            :                            sizeof(actions[n].conf));
    4615                 :          0 :                 handle[copied_n].index = n;
    4616                 :          0 :                 copied_n++;
    4617                 :            :         }
    4618                 :          0 :         n++;
    4619                 :          0 :         *indir_n = copied_n;
    4620         [ #  # ]:          0 :         if (!copied_n)
    4621                 :            :                 return 0;
    4622                 :          0 :         actions_size = sizeof(struct rte_flow_action) * n;
    4623                 :          0 :         translated = mlx5_malloc(MLX5_MEM_ZERO, actions_size, 0, SOCKET_ID_ANY);
    4624         [ #  # ]:          0 :         if (!translated) {
    4625                 :          0 :                 rte_errno = ENOMEM;
    4626                 :          0 :                 return -ENOMEM;
    4627                 :            :         }
    4628                 :            :         memcpy(translated, actions, actions_size);
    4629         [ #  # ]:          0 :         for (handle_end = handle + copied_n; handle < handle_end; handle++) {
    4630                 :            :                 struct mlx5_shared_action_rss *shared_rss;
    4631                 :          0 :                 uint32_t act_idx = (uint32_t)(uintptr_t)handle->action;
    4632                 :          0 :                 uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
    4633                 :          0 :                 uint32_t idx = act_idx &
    4634                 :            :                                ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
    4635                 :            : 
    4636   [ #  #  #  #  :          0 :                 switch (type) {
                   #  # ]
    4637                 :          0 :                 case MLX5_INDIRECT_ACTION_TYPE_RSS:
    4638                 :          0 :                         shared_rss = mlx5_ipool_get
    4639                 :          0 :                           (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
    4640                 :          0 :                         translated[handle->index].type =
    4641                 :            :                                 RTE_FLOW_ACTION_TYPE_RSS;
    4642                 :          0 :                         translated[handle->index].conf =
    4643                 :          0 :                                 &shared_rss->origin;
    4644                 :          0 :                         break;
    4645                 :          0 :                 case MLX5_INDIRECT_ACTION_TYPE_COUNT:
    4646                 :          0 :                         translated[handle->index].type =
    4647                 :            :                                                 (enum rte_flow_action_type)
    4648                 :            :                                                 MLX5_RTE_FLOW_ACTION_TYPE_COUNT;
    4649                 :          0 :                         translated[handle->index].conf = (void *)(uintptr_t)idx;
    4650                 :          0 :                         break;
    4651                 :          0 :                 case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
    4652                 :          0 :                         translated[handle->index].type =
    4653                 :            :                                                 (enum rte_flow_action_type)
    4654                 :            :                                                 MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK;
    4655                 :          0 :                         translated[handle->index].conf = (void *)(uintptr_t)idx;
    4656                 :          0 :                         break;
    4657                 :          0 :                 case MLX5_INDIRECT_ACTION_TYPE_AGE:
    4658         [ #  # ]:          0 :                         if (priv->sh->flow_hit_aso_en) {
    4659                 :          0 :                                 translated[handle->index].type =
    4660                 :            :                                         (enum rte_flow_action_type)
    4661                 :            :                                         MLX5_RTE_FLOW_ACTION_TYPE_AGE;
    4662                 :          0 :                                 translated[handle->index].conf =
    4663                 :          0 :                                                          (void *)(uintptr_t)idx;
    4664                 :          0 :                                 break;
    4665                 :            :                         }
    4666                 :            :                         /* Fall-through */
    4667                 :            :                 case MLX5_INDIRECT_ACTION_TYPE_CT:
    4668         [ #  # ]:          0 :                         if (priv->sh->ct_aso_en) {
    4669                 :          0 :                                 translated[handle->index].type =
    4670                 :            :                                         RTE_FLOW_ACTION_TYPE_CONNTRACK;
    4671                 :          0 :                                 translated[handle->index].conf =
    4672                 :          0 :                                                          (void *)(uintptr_t)idx;
    4673                 :          0 :                                 break;
    4674                 :            :                         }
    4675                 :            :                         /* Fall-through */
    4676                 :            :                 default:
    4677                 :          0 :                         mlx5_free(translated);
    4678                 :          0 :                         return rte_flow_error_set
    4679                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
    4680                 :            :                                  NULL, "invalid indirect action type");
    4681                 :            :                 }
    4682                 :            :         }
    4683                 :          0 :         *translated_actions = translated;
    4684                 :          0 :         return 0;
    4685                 :            : }
    4686                 :            : 
    4687                 :            : /**
    4688                 :            :  * Get Shared RSS action from the action list.
    4689                 :            :  *
    4690                 :            :  * @param[in] dev
    4691                 :            :  *   Pointer to Ethernet device.
    4692                 :            :  * @param[in] shared
    4693                 :            :  *   Pointer to the list of actions.
    4694                 :            :  * @param[in] shared_n
    4695                 :            :  *   Actions list length.
    4696                 :            :  *
    4697                 :            :  * @return
    4698                 :            :  *   The MLX5 RSS action ID if exists, otherwise return 0.
    4699                 :            :  */
    4700                 :            : static uint32_t
    4701                 :          0 : flow_get_shared_rss_action(struct rte_eth_dev *dev,
    4702                 :            :                            struct mlx5_translated_action_handle *handle,
    4703                 :            :                            int shared_n)
    4704                 :            : {
    4705                 :            :         struct mlx5_translated_action_handle *handle_end;
    4706                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4707                 :            :         struct mlx5_shared_action_rss *shared_rss;
    4708                 :            : 
    4709                 :            : 
    4710         [ #  # ]:          0 :         for (handle_end = handle + shared_n; handle < handle_end; handle++) {
    4711                 :          0 :                 uint32_t act_idx = (uint32_t)(uintptr_t)handle->action;
    4712                 :          0 :                 uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
    4713                 :          0 :                 uint32_t idx = act_idx &
    4714                 :            :                                ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
    4715         [ #  # ]:          0 :                 switch (type) {
    4716                 :          0 :                 case MLX5_INDIRECT_ACTION_TYPE_RSS:
    4717                 :          0 :                         shared_rss = mlx5_ipool_get
    4718                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
    4719                 :            :                                                                            idx);
    4720                 :          0 :                         rte_atomic_fetch_add_explicit(&shared_rss->refcnt, 1,
    4721                 :            :                                            rte_memory_order_relaxed);
    4722                 :          0 :                         return idx;
    4723                 :            :                 default:
    4724                 :            :                         break;
    4725                 :            :                 }
    4726                 :            :         }
    4727                 :            :         return 0;
    4728                 :            : }
    4729                 :            : 
    4730                 :            : static unsigned int
    4731                 :            : find_graph_root(uint32_t rss_level)
    4732                 :            : {
    4733                 :          0 :         return rss_level < 2 ? MLX5_EXPANSION_ROOT :
    4734                 :            :                                MLX5_EXPANSION_ROOT_OUTER;
    4735                 :            : }
    4736                 :            : 
    4737                 :            : /**
    4738                 :            :  *  Get layer flags from the prefix flow.
    4739                 :            :  *
    4740                 :            :  *  Some flows may be split to several subflows, the prefix subflow gets the
    4741                 :            :  *  match items and the suffix sub flow gets the actions.
    4742                 :            :  *  Some actions need the user defined match item flags to get the detail for
    4743                 :            :  *  the action.
    4744                 :            :  *  This function helps the suffix flow to get the item layer flags from prefix
    4745                 :            :  *  subflow.
    4746                 :            :  *
    4747                 :            :  * @param[in] dev_flow
    4748                 :            :  *   Pointer the created prefix subflow.
    4749                 :            :  *
    4750                 :            :  * @return
    4751                 :            :  *   The layers get from prefix subflow.
    4752                 :            :  */
    4753                 :            : static inline uint64_t
    4754                 :          0 : flow_get_prefix_layer_flags(struct mlx5_flow *dev_flow)
    4755                 :            : {
    4756                 :            :         uint64_t layers = 0;
    4757                 :            : 
    4758                 :            :         /*
    4759                 :            :          * Layers bits could be localization, but usually the compiler will
    4760                 :            :          * help to do the optimization work for source code.
    4761                 :            :          * If no decap actions, use the layers directly.
    4762                 :            :          */
    4763         [ #  # ]:          0 :         if (!(dev_flow->act_flags & MLX5_FLOW_ACTION_DECAP))
    4764                 :          0 :                 return dev_flow->handle->layers;
    4765                 :            :         /* Convert L3 layers with decap action. */
    4766         [ #  # ]:          0 :         if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L3_IPV4)
    4767                 :            :                 layers |= MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    4768         [ #  # ]:          0 :         else if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L3_IPV6)
    4769                 :            :                 layers |= MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    4770                 :            :         /* Convert L4 layers with decap action.  */
    4771         [ #  # ]:          0 :         if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L4_TCP)
    4772                 :          0 :                 layers |= MLX5_FLOW_LAYER_OUTER_L4_TCP;
    4773         [ #  # ]:          0 :         else if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L4_UDP)
    4774                 :          0 :                 layers |= MLX5_FLOW_LAYER_OUTER_L4_UDP;
    4775                 :            :         return layers;
    4776                 :            : }
    4777                 :            : 
    4778                 :            : /**
    4779                 :            :  * Get metadata split action information.
    4780                 :            :  *
    4781                 :            :  * @param[in] actions
    4782                 :            :  *   Pointer to the list of actions.
    4783                 :            :  * @param[out] qrss
    4784                 :            :  *   Pointer to the return pointer.
    4785                 :            :  * @param[out] qrss_type
    4786                 :            :  *   Pointer to the action type to return. RTE_FLOW_ACTION_TYPE_END is returned
    4787                 :            :  *   if no QUEUE/RSS is found.
    4788                 :            :  * @param[out] encap_idx
    4789                 :            :  *   Pointer to the index of the encap action if exists, otherwise the last
    4790                 :            :  *   action index.
    4791                 :            :  *
    4792                 :            :  * @return
    4793                 :            :  *   Total number of actions.
    4794                 :            :  */
    4795                 :            : static int
    4796                 :          0 : flow_parse_metadata_split_actions_info(const struct rte_flow_action actions[],
    4797                 :            :                                        const struct rte_flow_action **qrss,
    4798                 :            :                                        int *encap_idx)
    4799                 :            : {
    4800                 :            :         const struct rte_flow_action_raw_encap *raw_encap;
    4801                 :            :         int actions_n = 0;
    4802                 :            :         int raw_decap_idx = -1;
    4803                 :            : 
    4804                 :          0 :         *encap_idx = -1;
    4805         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    4806   [ #  #  #  #  :          0 :                 switch (actions->type) {
                      # ]
    4807                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    4808                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    4809                 :          0 :                         *encap_idx = actions_n;
    4810                 :          0 :                         break;
    4811                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    4812                 :            :                         raw_decap_idx = actions_n;
    4813                 :          0 :                         break;
    4814                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    4815                 :          0 :                         raw_encap = actions->conf;
    4816         [ #  # ]:          0 :                         if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
    4817                 :          0 :                                 *encap_idx = raw_decap_idx != -1 ?
    4818         [ #  # ]:          0 :                                                       raw_decap_idx : actions_n;
    4819                 :            :                         break;
    4820                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    4821                 :            :                 case RTE_FLOW_ACTION_TYPE_RSS:
    4822                 :          0 :                         *qrss = actions;
    4823                 :          0 :                         break;
    4824                 :            :                 default:
    4825                 :            :                         break;
    4826                 :            :                 }
    4827                 :          0 :                 actions_n++;
    4828                 :            :         }
    4829         [ #  # ]:          0 :         if (*encap_idx == -1)
    4830                 :          0 :                 *encap_idx = actions_n;
    4831                 :            :         /* Count RTE_FLOW_ACTION_TYPE_END. */
    4832                 :          0 :         return actions_n + 1;
    4833                 :            : }
    4834                 :            : 
    4835                 :            : /**
    4836                 :            :  * Check if the action will change packet.
    4837                 :            :  *
    4838                 :            :  * @param dev
    4839                 :            :  *   Pointer to Ethernet device.
    4840                 :            :  * @param[in] type
    4841                 :            :  *   action type.
    4842                 :            :  *
    4843                 :            :  * @return
    4844                 :            :  *   true if action will change packet, false otherwise.
    4845                 :            :  */
    4846                 :          0 : static bool flow_check_modify_action_type(struct rte_eth_dev *dev,
    4847                 :            :                                           enum rte_flow_action_type type)
    4848                 :            : {
    4849                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4850                 :            : 
    4851      [ #  #  # ]:          0 :         switch (type) {
    4852                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
    4853                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    4854                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
    4855                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
    4856                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
    4857                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
    4858                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
    4859                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    4860                 :            :         case RTE_FLOW_ACTION_TYPE_DEC_TTL:
    4861                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TTL:
    4862                 :            :         case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
    4863                 :            :         case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
    4864                 :            :         case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
    4865                 :            :         case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
    4866                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
    4867                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
    4868                 :            :         case RTE_FLOW_ACTION_TYPE_SET_META:
    4869                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TAG:
    4870                 :            :         case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    4871                 :            :         case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    4872                 :            :         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    4873                 :            :         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    4874                 :            :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    4875                 :            :         case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    4876                 :            :         case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    4877                 :            :         case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    4878                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    4879                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    4880                 :            :         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    4881                 :            :                 return true;
    4882                 :          0 :         case RTE_FLOW_ACTION_TYPE_FLAG:
    4883                 :            :         case RTE_FLOW_ACTION_TYPE_MARK:
    4884         [ #  # ]:          0 :                 if (priv->sh->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    4885                 :            :                     priv->sh->config.dv_xmeta_en != MLX5_XMETA_MODE_META32_HWS)
    4886                 :            :                         return true;
    4887                 :            :                 else
    4888                 :          0 :                         return false;
    4889                 :          0 :         default:
    4890                 :          0 :                 return false;
    4891                 :            :         }
    4892                 :            : }
    4893                 :            : 
    4894                 :            : /**
    4895                 :            :  * Check meter action from the action list.
    4896                 :            :  *
    4897                 :            :  * @param dev
    4898                 :            :  *   Pointer to Ethernet device.
    4899                 :            :  * @param[in] actions
    4900                 :            :  *   Pointer to the list of actions.
    4901                 :            :  * @param[out] has_mtr
    4902                 :            :  *   Pointer to the meter exist flag.
    4903                 :            :  * @param[out] has_modify
    4904                 :            :  *   Pointer to the flag showing there's packet change action.
    4905                 :            :  * @param[out] meter_id
    4906                 :            :  *   Pointer to the meter id.
    4907                 :            :  *
    4908                 :            :  * @return
    4909                 :            :  *   Total number of actions.
    4910                 :            :  */
    4911                 :            : static int
    4912                 :          0 : flow_check_meter_action(struct rte_eth_dev *dev,
    4913                 :            :                         const struct rte_flow_action actions[],
    4914                 :            :                         bool *has_mtr, bool *has_modify, uint32_t *meter_id)
    4915                 :            : {
    4916                 :            :         const struct rte_flow_action_meter *mtr = NULL;
    4917                 :            :         int actions_n = 0;
    4918                 :            : 
    4919                 :            :         MLX5_ASSERT(has_mtr);
    4920                 :          0 :         *has_mtr = false;
    4921         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    4922         [ #  # ]:          0 :                 switch (actions->type) {
    4923                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    4924                 :          0 :                         mtr = actions->conf;
    4925                 :          0 :                         *meter_id = mtr->mtr_id;
    4926                 :          0 :                         *has_mtr = true;
    4927                 :          0 :                         break;
    4928                 :            :                 default:
    4929                 :            :                         break;
    4930                 :            :                 }
    4931         [ #  # ]:          0 :                 if (!*has_mtr)
    4932                 :          0 :                         *has_modify |= flow_check_modify_action_type(dev,
    4933                 :          0 :                                                                 actions->type);
    4934                 :          0 :                 actions_n++;
    4935                 :            :         }
    4936                 :            :         /* Count RTE_FLOW_ACTION_TYPE_END. */
    4937                 :          0 :         return actions_n + 1;
    4938                 :            : }
    4939                 :            : 
    4940                 :            : /**
    4941                 :            :  * Check if the flow should be split due to hairpin.
    4942                 :            :  * The reason for the split is that in current HW we can't
    4943                 :            :  * support encap and push-vlan on Rx, so if a flow contains
    4944                 :            :  * these actions we move it to Tx.
    4945                 :            :  *
    4946                 :            :  * @param dev
    4947                 :            :  *   Pointer to Ethernet device.
    4948                 :            :  * @param[in] attr
    4949                 :            :  *   Flow rule attributes.
    4950                 :            :  * @param[in] actions
    4951                 :            :  *   Associated actions (list terminated by the END action).
    4952                 :            :  *
    4953                 :            :  * @return
    4954                 :            :  *   > 0 the number of actions and the flow should be split,
    4955                 :            :  *   0 when no split required.
    4956                 :            :  */
    4957                 :            : static int
    4958                 :          0 : flow_check_hairpin_split(struct rte_eth_dev *dev,
    4959                 :            :                          const struct rte_flow_attr *attr,
    4960                 :            :                          const struct rte_flow_action actions[])
    4961                 :            : {
    4962                 :            :         int queue_action = 0;
    4963                 :            :         int action_n = 0;
    4964                 :            :         int split = 0;
    4965                 :            :         int push_vlan = 0;
    4966                 :            :         const struct rte_flow_action_queue *queue;
    4967                 :            :         const struct rte_flow_action_rss *rss;
    4968                 :            :         const struct rte_flow_action_raw_encap *raw_encap;
    4969                 :            :         const struct rte_eth_hairpin_conf *conf;
    4970                 :            : 
    4971         [ #  # ]:          0 :         if (!attr->ingress)
    4972                 :            :                 return 0;
    4973         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    4974         [ #  # ]:          0 :                 if (actions->type == RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN)
    4975                 :            :                         push_vlan = 1;
    4976   [ #  #  #  #  :          0 :                 switch (actions->type) {
                   #  # ]
    4977                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    4978                 :          0 :                         queue = actions->conf;
    4979         [ #  # ]:          0 :                         if (queue == NULL)
    4980                 :            :                                 return 0;
    4981                 :          0 :                         conf = mlx5_rxq_get_hairpin_conf(dev, queue->index);
    4982   [ #  #  #  # ]:          0 :                         if (conf == NULL || conf->tx_explicit != 0)
    4983                 :            :                                 return 0;
    4984                 :            :                         queue_action = 1;
    4985                 :          0 :                         action_n++;
    4986                 :          0 :                         break;
    4987                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    4988                 :          0 :                         rss = actions->conf;
    4989   [ #  #  #  # ]:          0 :                         if (rss == NULL || rss->queue_num == 0)
    4990                 :            :                                 return 0;
    4991                 :          0 :                         conf = mlx5_rxq_get_hairpin_conf(dev, rss->queue[0]);
    4992   [ #  #  #  # ]:          0 :                         if (conf == NULL || conf->tx_explicit != 0)
    4993                 :            :                                 return 0;
    4994                 :            :                         queue_action = 1;
    4995                 :          0 :                         action_n++;
    4996                 :          0 :                         break;
    4997                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    4998                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    4999                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    5000                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    5001                 :          0 :                         split++;
    5002                 :          0 :                         action_n++;
    5003                 :          0 :                         break;
    5004                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    5005         [ #  # ]:          0 :                         if (push_vlan)
    5006                 :          0 :                                 split++;
    5007                 :          0 :                         action_n++;
    5008                 :          0 :                         break;
    5009                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    5010                 :          0 :                         raw_encap = actions->conf;
    5011         [ #  # ]:          0 :                         if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
    5012                 :          0 :                                 split++;
    5013                 :          0 :                         action_n++;
    5014                 :          0 :                         break;
    5015                 :          0 :                 default:
    5016                 :          0 :                         action_n++;
    5017                 :          0 :                         break;
    5018                 :            :                 }
    5019                 :            :         }
    5020         [ #  # ]:          0 :         if (split && queue_action)
    5021                 :          0 :                 return action_n;
    5022                 :            :         return 0;
    5023                 :            : }
    5024                 :            : 
    5025                 :            : int
    5026                 :          0 : flow_dv_mreg_match_cb(void *tool_ctx __rte_unused,
    5027                 :            :                       struct mlx5_list_entry *entry, void *cb_ctx)
    5028                 :            : {
    5029                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    5030                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res =
    5031                 :            :                                container_of(entry, typeof(*mcp_res), hlist_ent);
    5032                 :            : 
    5033                 :          0 :         return mcp_res->mark_id != *(uint32_t *)(ctx->data);
    5034                 :            : }
    5035                 :            : 
    5036                 :            : struct mlx5_list_entry *
    5037                 :          0 : flow_dv_mreg_create_cb(void *tool_ctx, void *cb_ctx)
    5038                 :            : {
    5039                 :            :         struct rte_eth_dev *dev = tool_ctx;
    5040                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5041                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    5042                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
    5043                 :          0 :         struct rte_flow_error *error = ctx->error;
    5044                 :          0 :         uint32_t idx = 0;
    5045                 :            :         int ret;
    5046                 :          0 :         uint32_t mark_id = *(uint32_t *)(ctx->data);
    5047                 :          0 :         struct rte_flow_attr attr = {
    5048                 :            :                 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP,
    5049                 :            :                 .ingress = 1,
    5050                 :            :         };
    5051                 :          0 :         struct mlx5_rte_flow_item_tag tag_spec = {
    5052                 :            :                 .data = mark_id,
    5053                 :            :         };
    5054                 :          0 :         struct rte_flow_item items[] = {
    5055                 :            :                 [1] = { .type = RTE_FLOW_ITEM_TYPE_END, },
    5056                 :            :         };
    5057                 :          0 :         struct rte_flow_action_mark ftag = {
    5058                 :            :                 .id = mark_id,
    5059                 :            :         };
    5060                 :          0 :         struct mlx5_flow_action_copy_mreg cp_mreg = {
    5061                 :            :                 .dst = REG_B,
    5062                 :            :                 .src = REG_NON,
    5063                 :            :         };
    5064                 :          0 :         struct rte_flow_action_jump jump = {
    5065                 :            :                 .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP,
    5066                 :            :         };
    5067                 :          0 :         struct rte_flow_action actions[] = {
    5068                 :            :                 [3] = { .type = RTE_FLOW_ACTION_TYPE_END, },
    5069                 :            :         };
    5070                 :            : 
    5071                 :            :         /* Fill the register fields in the flow. */
    5072                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    5073         [ #  # ]:          0 :         if (ret < 0)
    5074                 :            :                 return NULL;
    5075                 :          0 :         tag_spec.id = ret;
    5076                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_RX, 0, error);
    5077         [ #  # ]:          0 :         if (ret < 0)
    5078                 :            :                 return NULL;
    5079                 :          0 :         cp_mreg.src = ret;
    5080                 :            :         /* Provide the full width of FLAG specific value. */
    5081         [ #  # ]:          0 :         if (mark_id == (priv->sh->dv_regc0_mask & MLX5_FLOW_MARK_DEFAULT))
    5082                 :          0 :                 tag_spec.data = MLX5_FLOW_MARK_DEFAULT;
    5083                 :            :         /* Build a new flow. */
    5084         [ #  # ]:          0 :         if (mark_id != MLX5_DEFAULT_COPY_ID) {
    5085                 :          0 :                 items[0] = (struct rte_flow_item){
    5086                 :            :                         .type = (enum rte_flow_item_type)
    5087                 :            :                                 MLX5_RTE_FLOW_ITEM_TYPE_TAG,
    5088                 :            :                         .spec = &tag_spec,
    5089                 :            :                 };
    5090                 :          0 :                 items[1] = (struct rte_flow_item){
    5091                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    5092                 :            :                 };
    5093                 :          0 :                 actions[0] = (struct rte_flow_action){
    5094                 :            :                         .type = (enum rte_flow_action_type)
    5095                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_MARK,
    5096                 :            :                         .conf = &ftag,
    5097                 :            :                 };
    5098                 :          0 :                 actions[1] = (struct rte_flow_action){
    5099                 :            :                         .type = (enum rte_flow_action_type)
    5100                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
    5101                 :            :                         .conf = &cp_mreg,
    5102                 :            :                 };
    5103                 :          0 :                 actions[2] = (struct rte_flow_action){
    5104                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
    5105                 :            :                         .conf = &jump,
    5106                 :            :                 };
    5107                 :          0 :                 actions[3] = (struct rte_flow_action){
    5108                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
    5109                 :            :                 };
    5110                 :            :         } else {
    5111                 :            :                 /* Default rule, wildcard match. */
    5112                 :          0 :                 attr.priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR;
    5113                 :          0 :                 items[0] = (struct rte_flow_item){
    5114                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    5115                 :            :                 };
    5116                 :          0 :                 actions[0] = (struct rte_flow_action){
    5117                 :            :                         .type = (enum rte_flow_action_type)
    5118                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
    5119                 :            :                         .conf = &cp_mreg,
    5120                 :            :                 };
    5121                 :          0 :                 actions[1] = (struct rte_flow_action){
    5122                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
    5123                 :            :                         .conf = &jump,
    5124                 :            :                 };
    5125                 :          0 :                 actions[2] = (struct rte_flow_action){
    5126                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
    5127                 :            :                 };
    5128                 :            :         }
    5129                 :            :         /* Build a new entry. */
    5130                 :          0 :         mcp_res = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MCP], &idx);
    5131         [ #  # ]:          0 :         if (!mcp_res) {
    5132                 :          0 :                 rte_errno = ENOMEM;
    5133                 :          0 :                 return NULL;
    5134                 :            :         }
    5135                 :          0 :         mcp_res->idx = idx;
    5136                 :          0 :         mcp_res->mark_id = mark_id;
    5137                 :            :         /*
    5138                 :            :          * The copy Flows are not included in any list. There
    5139                 :            :          * ones are referenced from other Flows and can not
    5140                 :            :          * be applied, removed, deleted in arbitrary order
    5141                 :            :          * by list traversing.
    5142                 :            :          */
    5143                 :          0 :         mcp_res->rix_flow = mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_MCP,
    5144                 :            :                                         &attr, items, actions, false, error);
    5145         [ #  # ]:          0 :         if (!mcp_res->rix_flow) {
    5146                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], idx);
    5147                 :          0 :                 return NULL;
    5148                 :            :         }
    5149                 :          0 :         return &mcp_res->hlist_ent;
    5150                 :            : }
    5151                 :            : 
    5152                 :            : struct mlx5_list_entry *
    5153                 :          0 : flow_dv_mreg_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
    5154                 :            :                       void *cb_ctx __rte_unused)
    5155                 :            : {
    5156                 :            :         struct rte_eth_dev *dev = tool_ctx;
    5157                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5158                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
    5159                 :          0 :         uint32_t idx = 0;
    5160                 :            : 
    5161                 :          0 :         mcp_res = mlx5_ipool_malloc(priv->sh->ipool[MLX5_IPOOL_MCP], &idx);
    5162         [ #  # ]:          0 :         if (!mcp_res) {
    5163                 :          0 :                 rte_errno = ENOMEM;
    5164                 :          0 :                 return NULL;
    5165                 :            :         }
    5166                 :            :         memcpy(mcp_res, oentry, sizeof(*mcp_res));
    5167                 :          0 :         mcp_res->idx = idx;
    5168                 :          0 :         return &mcp_res->hlist_ent;
    5169                 :            : }
    5170                 :            : 
    5171                 :            : void
    5172                 :          0 : flow_dv_mreg_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    5173                 :            : {
    5174                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res =
    5175                 :            :                                container_of(entry, typeof(*mcp_res), hlist_ent);
    5176                 :            :         struct rte_eth_dev *dev = tool_ctx;
    5177                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5178                 :            : 
    5179                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
    5180                 :          0 : }
    5181                 :            : 
    5182                 :            : /**
    5183                 :            :  * Add a flow of copying flow metadata registers in RX_CP_TBL.
    5184                 :            :  *
    5185                 :            :  * As mark_id is unique, if there's already a registered flow for the mark_id,
    5186                 :            :  * return by increasing the reference counter of the resource. Otherwise, create
    5187                 :            :  * the resource (mcp_res) and flow.
    5188                 :            :  *
    5189                 :            :  * Flow looks like,
    5190                 :            :  *   - If ingress port is ANY and reg_c[1] is mark_id,
    5191                 :            :  *     flow_tag := mark_id, reg_b := reg_c[0] and jump to RX_ACT_TBL.
    5192                 :            :  *
    5193                 :            :  * For default flow (zero mark_id), flow is like,
    5194                 :            :  *   - If ingress port is ANY,
    5195                 :            :  *     reg_b := reg_c[0] and jump to RX_ACT_TBL.
    5196                 :            :  *
    5197                 :            :  * @param dev
    5198                 :            :  *   Pointer to Ethernet device.
    5199                 :            :  * @param mark_id
    5200                 :            :  *   ID of MARK action, zero means default flow for META.
    5201                 :            :  * @param[out] error
    5202                 :            :  *   Perform verbose error reporting if not NULL.
    5203                 :            :  *
    5204                 :            :  * @return
    5205                 :            :  *   Associated resource on success, NULL otherwise and rte_errno is set.
    5206                 :            :  */
    5207                 :            : static struct mlx5_flow_mreg_copy_resource *
    5208                 :          0 : flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id,
    5209                 :            :                           struct rte_flow_error *error)
    5210                 :            : {
    5211                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5212                 :            :         struct mlx5_list_entry *entry;
    5213                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    5214                 :            :                 .dev = dev,
    5215                 :            :                 .error = error,
    5216                 :            :                 .data = &mark_id,
    5217                 :            :         };
    5218                 :            : 
    5219                 :            :         /* Check if already registered. */
    5220                 :            :         MLX5_ASSERT(priv->sh->mreg_cp_tbl);
    5221                 :          0 :         entry = mlx5_hlist_register(priv->sh->mreg_cp_tbl, mark_id, &ctx);
    5222         [ #  # ]:          0 :         if (!entry)
    5223                 :          0 :                 return NULL;
    5224                 :            :         return container_of(entry, struct mlx5_flow_mreg_copy_resource,
    5225                 :            :                             hlist_ent);
    5226                 :            : }
    5227                 :            : 
    5228                 :            : void
    5229                 :          0 : flow_dv_mreg_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    5230                 :            : {
    5231                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res =
    5232                 :            :                                container_of(entry, typeof(*mcp_res), hlist_ent);
    5233                 :            :         struct rte_eth_dev *dev = tool_ctx;
    5234                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5235                 :            : 
    5236                 :            :         MLX5_ASSERT(mcp_res->rix_flow);
    5237                 :          0 :         mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_MCP, mcp_res->rix_flow);
    5238                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
    5239                 :          0 : }
    5240                 :            : 
    5241                 :            : /**
    5242                 :            :  * Release flow in RX_CP_TBL.
    5243                 :            :  *
    5244                 :            :  * @param dev
    5245                 :            :  *   Pointer to Ethernet device.
    5246                 :            :  * @flow
    5247                 :            :  *   Parent flow for wich copying is provided.
    5248                 :            :  */
    5249                 :            : static void
    5250                 :          0 : flow_mreg_del_copy_action(struct rte_eth_dev *dev,
    5251                 :            :                           struct rte_flow *flow)
    5252                 :            : {
    5253                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
    5254                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5255                 :            : 
    5256         [ #  # ]:          0 :         if (!flow->rix_mreg_copy)
    5257                 :            :                 return;
    5258                 :          0 :         mcp_res = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MCP],
    5259                 :            :                                  flow->rix_mreg_copy);
    5260   [ #  #  #  # ]:          0 :         if (!mcp_res || !priv->sh->mreg_cp_tbl)
    5261                 :            :                 return;
    5262                 :            :         MLX5_ASSERT(mcp_res->rix_flow);
    5263                 :          0 :         mlx5_hlist_unregister(priv->sh->mreg_cp_tbl, &mcp_res->hlist_ent);
    5264                 :          0 :         flow->rix_mreg_copy = 0;
    5265                 :            : }
    5266                 :            : 
    5267                 :            : /**
    5268                 :            :  * Remove the default copy action from RX_CP_TBL.
    5269                 :            :  *
    5270                 :            :  * This functions is called in the mlx5_dev_start(). No thread safe
    5271                 :            :  * is guaranteed.
    5272                 :            :  *
    5273                 :            :  * @param dev
    5274                 :            :  *   Pointer to Ethernet device.
    5275                 :            :  */
    5276                 :            : static void
    5277                 :          0 : flow_mreg_del_default_copy_action(struct rte_eth_dev *dev)
    5278                 :            : {
    5279                 :            :         struct mlx5_list_entry *entry;
    5280                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5281                 :            :         struct mlx5_flow_cb_ctx ctx;
    5282                 :            :         uint32_t mark_id;
    5283                 :            : 
    5284                 :            :         /* Check if default flow is registered. */
    5285         [ #  # ]:          0 :         if (!priv->sh->mreg_cp_tbl)
    5286                 :          0 :                 return;
    5287                 :          0 :         mark_id = MLX5_DEFAULT_COPY_ID;
    5288                 :          0 :         ctx.data = &mark_id;
    5289                 :          0 :         entry = mlx5_hlist_lookup(priv->sh->mreg_cp_tbl, mark_id, &ctx);
    5290         [ #  # ]:          0 :         if (!entry)
    5291                 :            :                 return;
    5292                 :          0 :         mlx5_hlist_unregister(priv->sh->mreg_cp_tbl, entry);
    5293                 :            : }
    5294                 :            : 
    5295                 :            : /**
    5296                 :            :  * Add the default copy action in RX_CP_TBL.
    5297                 :            :  *
    5298                 :            :  * This functions is called in the mlx5_dev_start(). No thread safe
    5299                 :            :  * is guaranteed.
    5300                 :            :  *
    5301                 :            :  * @param dev
    5302                 :            :  *   Pointer to Ethernet device.
    5303                 :            :  * @param[out] error
    5304                 :            :  *   Perform verbose error reporting if not NULL.
    5305                 :            :  *
    5306                 :            :  * @return
    5307                 :            :  *   0 for success, negative value otherwise and rte_errno is set.
    5308                 :            :  */
    5309                 :            : static int
    5310                 :          0 : flow_mreg_add_default_copy_action(struct rte_eth_dev *dev,
    5311                 :            :                                   struct rte_flow_error *error)
    5312                 :            : {
    5313                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5314                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
    5315                 :            :         struct mlx5_flow_cb_ctx ctx;
    5316                 :            :         uint32_t mark_id;
    5317                 :            : 
    5318                 :            :         /* Check whether extensive metadata feature is engaged. */
    5319         [ #  # ]:          0 :         if (!priv->sh->config.dv_flow_en ||
    5320   [ #  #  #  # ]:          0 :             priv->sh->config.dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
    5321                 :          0 :             !mlx5_flow_ext_mreg_supported(dev) ||
    5322         [ #  # ]:          0 :             !priv->sh->dv_regc0_mask)
    5323                 :          0 :                 return 0;
    5324                 :            :         /*
    5325                 :            :          * Add default mreg copy flow may be called multiple time, but
    5326                 :            :          * only be called once in stop. Avoid register it twice.
    5327                 :            :          */
    5328                 :          0 :         mark_id = MLX5_DEFAULT_COPY_ID;
    5329                 :          0 :         ctx.data = &mark_id;
    5330         [ #  # ]:          0 :         if (mlx5_hlist_lookup(priv->sh->mreg_cp_tbl, mark_id, &ctx))
    5331                 :            :                 return 0;
    5332                 :          0 :         mcp_res = flow_mreg_add_copy_action(dev, mark_id, error);
    5333         [ #  # ]:          0 :         if (!mcp_res)
    5334                 :          0 :                 return -rte_errno;
    5335                 :            :         return 0;
    5336                 :            : }
    5337                 :            : 
    5338                 :            : /**
    5339                 :            :  * Add a flow of copying flow metadata registers in RX_CP_TBL.
    5340                 :            :  *
    5341                 :            :  * All the flow having Q/RSS action should be split by
    5342                 :            :  * flow_mreg_split_qrss_prep() to pass by RX_CP_TBL. A flow in the RX_CP_TBL
    5343                 :            :  * performs the following,
    5344                 :            :  *   - CQE->flow_tag := reg_c[1] (MARK)
    5345                 :            :  *   - CQE->flow_table_metadata (reg_b) := reg_c[0] (META)
    5346                 :            :  * As CQE's flow_tag is not a register, it can't be simply copied from reg_c[1]
    5347                 :            :  * but there should be a flow per each MARK ID set by MARK action.
    5348                 :            :  *
    5349                 :            :  * For the aforementioned reason, if there's a MARK action in flow's action
    5350                 :            :  * list, a corresponding flow should be added to the RX_CP_TBL in order to copy
    5351                 :            :  * the MARK ID to CQE's flow_tag like,
    5352                 :            :  *   - If reg_c[1] is mark_id,
    5353                 :            :  *     flow_tag := mark_id, reg_b := reg_c[0] and jump to RX_ACT_TBL.
    5354                 :            :  *
    5355                 :            :  * For SET_META action which stores value in reg_c[0], as the destination is
    5356                 :            :  * also a flow metadata register (reg_b), adding a default flow is enough. Zero
    5357                 :            :  * MARK ID means the default flow. The default flow looks like,
    5358                 :            :  *   - For all flow, reg_b := reg_c[0] and jump to RX_ACT_TBL.
    5359                 :            :  *
    5360                 :            :  * @param dev
    5361                 :            :  *   Pointer to Ethernet device.
    5362                 :            :  * @param flow
    5363                 :            :  *   Pointer to flow structure.
    5364                 :            :  * @param[in] actions
    5365                 :            :  *   Pointer to the list of actions.
    5366                 :            :  * @param[out] error
    5367                 :            :  *   Perform verbose error reporting if not NULL.
    5368                 :            :  *
    5369                 :            :  * @return
    5370                 :            :  *   0 on success, negative value otherwise and rte_errno is set.
    5371                 :            :  */
    5372                 :            : static int
    5373                 :          0 : flow_mreg_update_copy_table(struct rte_eth_dev *dev,
    5374                 :            :                             struct rte_flow *flow,
    5375                 :            :                             const struct rte_flow_action *actions,
    5376                 :            :                             struct rte_flow_error *error)
    5377                 :            : {
    5378                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5379                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    5380                 :            :         struct mlx5_flow_mreg_copy_resource *mcp_res;
    5381                 :            :         const struct rte_flow_action_mark *mark;
    5382                 :            : 
    5383                 :            :         /* Check whether extensive metadata feature is engaged. */
    5384         [ #  # ]:          0 :         if (!config->dv_flow_en ||
    5385   [ #  #  #  # ]:          0 :             config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
    5386                 :          0 :             !mlx5_flow_ext_mreg_supported(dev) ||
    5387         [ #  # ]:          0 :             !priv->sh->dv_regc0_mask)
    5388                 :          0 :                 return 0;
    5389                 :            :         /* Find MARK action. */
    5390         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    5391      [ #  #  # ]:          0 :                 switch (actions->type) {
    5392                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    5393                 :          0 :                         mcp_res = flow_mreg_add_copy_action
    5394                 :            :                                 (dev, MLX5_FLOW_MARK_DEFAULT, error);
    5395         [ #  # ]:          0 :                         if (!mcp_res)
    5396                 :          0 :                                 return -rte_errno;
    5397                 :          0 :                         flow->rix_mreg_copy = mcp_res->idx;
    5398                 :          0 :                         return 0;
    5399                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    5400                 :          0 :                         mark = (const struct rte_flow_action_mark *)
    5401                 :            :                                 actions->conf;
    5402                 :            :                         mcp_res =
    5403                 :          0 :                                 flow_mreg_add_copy_action(dev, mark->id, error);
    5404         [ #  # ]:          0 :                         if (!mcp_res)
    5405                 :          0 :                                 return -rte_errno;
    5406                 :          0 :                         flow->rix_mreg_copy = mcp_res->idx;
    5407                 :          0 :                         return 0;
    5408                 :            :                 default:
    5409                 :            :                         break;
    5410                 :            :                 }
    5411                 :            :         }
    5412                 :            :         return 0;
    5413                 :            : }
    5414                 :            : 
    5415                 :            : #define MLX5_MAX_SPLIT_ACTIONS 24
    5416                 :            : #define MLX5_MAX_SPLIT_ITEMS 24
    5417                 :            : 
    5418                 :            : /**
    5419                 :            :  * Split the hairpin flow.
    5420                 :            :  * Since HW can't support encap and push-vlan on Rx, we move these
    5421                 :            :  * actions to Tx.
    5422                 :            :  * If the count action is after the encap then we also
    5423                 :            :  * move the count action. in this case the count will also measure
    5424                 :            :  * the outer bytes.
    5425                 :            :  *
    5426                 :            :  * @param dev
    5427                 :            :  *   Pointer to Ethernet device.
    5428                 :            :  * @param[in] actions
    5429                 :            :  *   Associated actions (list terminated by the END action).
    5430                 :            :  * @param[out] actions_rx
    5431                 :            :  *   Rx flow actions.
    5432                 :            :  * @param[out] actions_tx
    5433                 :            :  *   Tx flow actions..
    5434                 :            :  * @param[out] pattern_tx
    5435                 :            :  *   The pattern items for the Tx flow.
    5436                 :            :  * @param[out] flow_id
    5437                 :            :  *   The flow ID connected to this flow.
    5438                 :            :  *
    5439                 :            :  * @return
    5440                 :            :  *   0 on success.
    5441                 :            :  */
    5442                 :            : static int
    5443                 :          0 : flow_hairpin_split(struct rte_eth_dev *dev,
    5444                 :            :                    const struct rte_flow_action actions[],
    5445                 :            :                    struct rte_flow_action actions_rx[],
    5446                 :            :                    struct rte_flow_action actions_tx[],
    5447                 :            :                    struct rte_flow_item pattern_tx[],
    5448                 :            :                    uint32_t flow_id)
    5449                 :            : {
    5450                 :            :         const struct rte_flow_action_raw_encap *raw_encap;
    5451                 :            :         const struct rte_flow_action_raw_decap *raw_decap;
    5452                 :            :         struct mlx5_rte_flow_action_set_tag *set_tag;
    5453                 :            :         struct rte_flow_action *tag_action;
    5454                 :            :         struct mlx5_rte_flow_item_tag *tag_item;
    5455                 :            :         struct rte_flow_item *item;
    5456                 :            :         char *addr;
    5457                 :            :         int push_vlan = 0;
    5458                 :            :         int encap = 0;
    5459                 :            : 
    5460         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    5461         [ #  # ]:          0 :                 if (actions->type == RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN)
    5462                 :            :                         push_vlan = 1;
    5463   [ #  #  #  #  :          0 :                 switch (actions->type) {
                   #  # ]
    5464                 :            :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    5465                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    5466                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    5467                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    5468                 :            :                         rte_memcpy(actions_tx, actions,
    5469                 :            :                                sizeof(struct rte_flow_action));
    5470                 :          0 :                         actions_tx++;
    5471                 :          0 :                         break;
    5472                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    5473         [ #  # ]:          0 :                         if (push_vlan) {
    5474                 :            :                                 rte_memcpy(actions_tx, actions,
    5475                 :            :                                            sizeof(struct rte_flow_action));
    5476                 :          0 :                                 actions_tx++;
    5477                 :            :                         } else {
    5478                 :            :                                 rte_memcpy(actions_rx, actions,
    5479                 :            :                                            sizeof(struct rte_flow_action));
    5480                 :          0 :                                 actions_rx++;
    5481                 :            :                         }
    5482                 :            :                         break;
    5483                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    5484                 :            :                 case RTE_FLOW_ACTION_TYPE_AGE:
    5485         [ #  # ]:          0 :                         if (encap) {
    5486                 :            :                                 rte_memcpy(actions_tx, actions,
    5487                 :            :                                            sizeof(struct rte_flow_action));
    5488                 :          0 :                                 actions_tx++;
    5489                 :            :                         } else {
    5490                 :            :                                 rte_memcpy(actions_rx, actions,
    5491                 :            :                                            sizeof(struct rte_flow_action));
    5492                 :          0 :                                 actions_rx++;
    5493                 :            :                         }
    5494                 :            :                         break;
    5495                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    5496                 :          0 :                         raw_encap = actions->conf;
    5497         [ #  # ]:          0 :                         if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE) {
    5498                 :            :                                 memcpy(actions_tx, actions,
    5499                 :            :                                        sizeof(struct rte_flow_action));
    5500                 :          0 :                                 actions_tx++;
    5501                 :            :                                 encap = 1;
    5502                 :            :                         } else {
    5503                 :            :                                 rte_memcpy(actions_rx, actions,
    5504                 :            :                                            sizeof(struct rte_flow_action));
    5505                 :          0 :                                 actions_rx++;
    5506                 :            :                         }
    5507                 :            :                         break;
    5508                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    5509                 :          0 :                         raw_decap = actions->conf;
    5510         [ #  # ]:          0 :                         if (raw_decap->size < MLX5_ENCAPSULATION_DECISION_SIZE) {
    5511                 :            :                                 memcpy(actions_tx, actions,
    5512                 :            :                                        sizeof(struct rte_flow_action));
    5513                 :          0 :                                 actions_tx++;
    5514                 :            :                         } else {
    5515                 :            :                                 rte_memcpy(actions_rx, actions,
    5516                 :            :                                            sizeof(struct rte_flow_action));
    5517                 :          0 :                                 actions_rx++;
    5518                 :            :                         }
    5519                 :            :                         break;
    5520                 :            :                 default:
    5521                 :            :                         rte_memcpy(actions_rx, actions,
    5522                 :            :                                    sizeof(struct rte_flow_action));
    5523                 :          0 :                         actions_rx++;
    5524                 :          0 :                         break;
    5525                 :            :                 }
    5526                 :            :         }
    5527                 :            :         /* Add set meta action and end action for the Rx flow. */
    5528                 :            :         tag_action = actions_rx;
    5529                 :          0 :         tag_action->type = (enum rte_flow_action_type)
    5530                 :            :                            MLX5_RTE_FLOW_ACTION_TYPE_TAG;
    5531         [ #  # ]:          0 :         actions_rx++;
    5532                 :            :         rte_memcpy(actions_rx, actions, sizeof(struct rte_flow_action));
    5533                 :          0 :         actions_rx++;
    5534                 :            :         set_tag = (void *)actions_rx;
    5535                 :          0 :         *set_tag = (struct mlx5_rte_flow_action_set_tag) {
    5536                 :          0 :                 .id = mlx5_flow_get_reg_id(dev, MLX5_HAIRPIN_RX, 0, NULL),
    5537                 :            :                 .data = flow_id,
    5538                 :            :         };
    5539                 :            :         MLX5_ASSERT(set_tag->id > REG_NON);
    5540         [ #  # ]:          0 :         tag_action->conf = set_tag;
    5541                 :            :         /* Create Tx item list. */
    5542                 :            :         rte_memcpy(actions_tx, actions, sizeof(struct rte_flow_action));
    5543                 :          0 :         addr = (void *)&pattern_tx[2];
    5544                 :            :         item = pattern_tx;
    5545                 :          0 :         item->type = (enum rte_flow_item_type)
    5546                 :            :                      MLX5_RTE_FLOW_ITEM_TYPE_TAG;
    5547                 :            :         tag_item = (void *)addr;
    5548                 :          0 :         tag_item->data = flow_id;
    5549                 :          0 :         tag_item->id = mlx5_flow_get_reg_id(dev, MLX5_HAIRPIN_TX, 0, NULL);
    5550                 :            :         MLX5_ASSERT(set_tag->id > REG_NON);
    5551                 :          0 :         item->spec = tag_item;
    5552                 :          0 :         addr += sizeof(struct mlx5_rte_flow_item_tag);
    5553                 :            :         tag_item = (void *)addr;
    5554                 :          0 :         tag_item->data = UINT32_MAX;
    5555                 :          0 :         tag_item->id = UINT16_MAX;
    5556                 :          0 :         item->mask = tag_item;
    5557                 :          0 :         item->last = NULL;
    5558                 :            :         item++;
    5559                 :          0 :         item->type = RTE_FLOW_ITEM_TYPE_END;
    5560                 :          0 :         return 0;
    5561                 :            : }
    5562                 :            : 
    5563                 :            : /**
    5564                 :            :  * The last stage of splitting chain, just creates the subflow
    5565                 :            :  * without any modification.
    5566                 :            :  *
    5567                 :            :  * @param[in] dev
    5568                 :            :  *   Pointer to Ethernet device.
    5569                 :            :  * @param[in] flow
    5570                 :            :  *   Parent flow structure pointer.
    5571                 :            :  * @param[in, out] sub_flow
    5572                 :            :  *   Pointer to return the created subflow, may be NULL.
    5573                 :            :  * @param[in] attr
    5574                 :            :  *   Flow rule attributes.
    5575                 :            :  * @param[in] items
    5576                 :            :  *   Pattern specification (list terminated by the END pattern item).
    5577                 :            :  * @param[in] actions
    5578                 :            :  *   Associated actions (list terminated by the END action).
    5579                 :            :  * @param[in] flow_split_info
    5580                 :            :  *   Pointer to flow split info structure.
    5581                 :            :  * @param[out] error
    5582                 :            :  *   Perform verbose error reporting if not NULL.
    5583                 :            :  * @return
    5584                 :            :  *   0 on success, negative value otherwise
    5585                 :            :  */
    5586                 :            : static int
    5587                 :          0 : flow_create_split_inner(struct rte_eth_dev *dev,
    5588                 :            :                         struct rte_flow *flow,
    5589                 :            :                         struct mlx5_flow **sub_flow,
    5590                 :            :                         const struct rte_flow_attr *attr,
    5591                 :            :                         const struct rte_flow_item items[],
    5592                 :            :                         const struct rte_flow_action actions[],
    5593                 :            :                         struct mlx5_flow_split_info *flow_split_info,
    5594                 :            :                         struct rte_flow_error *error)
    5595                 :            : {
    5596                 :            :         struct mlx5_flow *dev_flow;
    5597                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
    5598                 :            : 
    5599                 :          0 :         dev_flow = flow_drv_prepare(dev, flow, attr, items, actions,
    5600                 :            :                                     flow_split_info->flow_idx, error);
    5601         [ #  # ]:          0 :         if (!dev_flow)
    5602                 :          0 :                 return -rte_errno;
    5603                 :          0 :         dev_flow->flow = flow;
    5604                 :          0 :         dev_flow->external = flow_split_info->external;
    5605                 :          0 :         dev_flow->skip_scale = flow_split_info->skip_scale;
    5606                 :            :         /* Subflow object was created, we must include one in the list. */
    5607                 :          0 :         SILIST_INSERT(&flow->dev_handles, dev_flow->handle_idx,
    5608                 :            :                       dev_flow->handle, next);
    5609                 :            :         /*
    5610                 :            :          * If dev_flow is as one of the suffix flow, some actions in suffix
    5611                 :            :          * flow may need some user defined item layer flags, and pass the
    5612                 :            :          * Metadata rxq mark flag to suffix flow as well.
    5613                 :            :          */
    5614         [ #  # ]:          0 :         if (flow_split_info->prefix_layers)
    5615                 :          0 :                 dev_flow->handle->layers = flow_split_info->prefix_layers;
    5616         [ #  # ]:          0 :         if (flow_split_info->prefix_mark) {
    5617                 :            :                 MLX5_ASSERT(wks);
    5618                 :          0 :                 wks->mark = 1;
    5619                 :            :         }
    5620         [ #  # ]:          0 :         if (sub_flow)
    5621                 :          0 :                 *sub_flow = dev_flow;
    5622                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
    5623                 :          0 :         dev_flow->dv.table_id = flow_split_info->table_id;
    5624                 :            : #endif
    5625                 :          0 :         return flow_drv_translate(dev, dev_flow, attr, items, actions, error);
    5626                 :            : }
    5627                 :            : 
    5628                 :            : /**
    5629                 :            :  * Get the sub policy of a meter.
    5630                 :            :  *
    5631                 :            :  * @param[in] dev
    5632                 :            :  *   Pointer to Ethernet device.
    5633                 :            :  * @param[in] flow
    5634                 :            :  *   Parent flow structure pointer.
    5635                 :            :  * @param wks
    5636                 :            :  *   Pointer to thread flow work space.
    5637                 :            :  * @param[in] attr
    5638                 :            :  *   Flow rule attributes.
    5639                 :            :  * @param[in] items
    5640                 :            :  *   Pattern specification (list terminated by the END pattern item).
    5641                 :            :  * @param[out] error
    5642                 :            :  *   Perform verbose error reporting if not NULL.
    5643                 :            :  *
    5644                 :            :  * @return
    5645                 :            :  *   Pointer to the meter sub policy, NULL otherwise and rte_errno is set.
    5646                 :            :  */
    5647                 :            : static struct mlx5_flow_meter_sub_policy *
    5648                 :          0 : get_meter_sub_policy(struct rte_eth_dev *dev,
    5649                 :            :                      struct rte_flow *flow,
    5650                 :            :                      struct mlx5_flow_workspace *wks,
    5651                 :            :                      const struct rte_flow_attr *attr,
    5652                 :            :                      const struct rte_flow_item items[],
    5653                 :            :                      struct rte_flow_error *error)
    5654                 :            : {
    5655                 :            :         struct mlx5_flow_meter_policy *policy;
    5656                 :            :         struct mlx5_flow_meter_policy *final_policy;
    5657                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
    5658                 :            : 
    5659                 :          0 :         policy = wks->policy;
    5660         [ #  # ]:          0 :         final_policy = policy->is_hierarchy ? wks->final_policy : policy;
    5661         [ #  # ]:          0 :         if (final_policy->is_rss || final_policy->is_queue) {
    5662                 :            :                 struct mlx5_flow_rss_desc rss_desc_v[MLX5_MTR_RTE_COLORS];
    5663                 :          0 :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS] = {0};
    5664                 :            :                 uint32_t i;
    5665                 :            : 
    5666                 :            :                 /*
    5667                 :            :                  * This is a tmp dev_flow,
    5668                 :            :                  * no need to register any matcher for it in translate.
    5669                 :            :                  */
    5670                 :          0 :                 wks->skip_matcher_reg = 1;
    5671         [ #  # ]:          0 :                 for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
    5672                 :          0 :                         struct mlx5_flow dev_flow = {0};
    5673                 :          0 :                         struct mlx5_flow_handle dev_handle = { {0} };
    5674                 :          0 :                         uint8_t fate = final_policy->act_cnt[i].fate_action;
    5675                 :            : 
    5676         [ #  # ]:          0 :                         if (fate == MLX5_FLOW_FATE_SHARED_RSS) {
    5677                 :          0 :                                 const struct rte_flow_action_rss *rss_act =
    5678                 :          0 :                                         final_policy->act_cnt[i].rss->conf;
    5679                 :          0 :                                 struct rte_flow_action rss_actions[2] = {
    5680                 :            :                                         [0] = {
    5681                 :            :                                         .type = RTE_FLOW_ACTION_TYPE_RSS,
    5682                 :            :                                         .conf = rss_act,
    5683                 :            :                                         },
    5684                 :            :                                         [1] = {
    5685                 :            :                                         .type = RTE_FLOW_ACTION_TYPE_END,
    5686                 :            :                                         .conf = NULL,
    5687                 :            :                                         }
    5688                 :            :                                 };
    5689                 :            : 
    5690                 :          0 :                                 dev_flow.handle = &dev_handle;
    5691                 :          0 :                                 dev_flow.ingress = attr->ingress;
    5692                 :          0 :                                 dev_flow.flow = flow;
    5693                 :            :                                 dev_flow.external = 0;
    5694                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
    5695                 :          0 :                                 dev_flow.dv.transfer = attr->transfer;
    5696                 :            : #endif
    5697                 :            :                                 /**
    5698                 :            :                                  * Translate RSS action to get rss hash fields.
    5699                 :            :                                  */
    5700         [ #  # ]:          0 :                                 if (flow_drv_translate(dev, &dev_flow, attr,
    5701                 :            :                                                 items, rss_actions, error))
    5702                 :          0 :                                         goto exit;
    5703                 :          0 :                                 rss_desc_v[i] = wks->rss_desc;
    5704                 :          0 :                                 rss_desc_v[i].symmetric_hash_function =
    5705                 :          0 :                                                 dev_flow.symmetric_hash_function;
    5706                 :          0 :                                 rss_desc_v[i].key_len = MLX5_RSS_HASH_KEY_LEN;
    5707                 :          0 :                                 rss_desc_v[i].hash_fields =
    5708                 :          0 :                                                 dev_flow.hash_fields;
    5709                 :          0 :                                 rss_desc_v[i].queue_num =
    5710                 :            :                                                 rss_desc_v[i].hash_fields ?
    5711         [ #  # ]:          0 :                                                 rss_desc_v[i].queue_num : 1;
    5712                 :          0 :                                 rss_desc_v[i].tunnel =
    5713                 :          0 :                                                 !!(dev_flow.handle->layers &
    5714                 :            :                                                    MLX5_FLOW_LAYER_TUNNEL);
    5715                 :            :                                 /* Use the RSS queues in the containers. */
    5716                 :          0 :                                 rss_desc_v[i].queue =
    5717                 :          0 :                                         (uint16_t *)(uintptr_t)rss_act->queue;
    5718                 :          0 :                                 rss_desc[i] = &rss_desc_v[i];
    5719         [ #  # ]:          0 :                         } else if (fate == MLX5_FLOW_FATE_QUEUE) {
    5720                 :            :                                 /* This is queue action. */
    5721                 :          0 :                                 rss_desc_v[i] = wks->rss_desc;
    5722                 :          0 :                                 rss_desc_v[i].key_len = 0;
    5723                 :          0 :                                 rss_desc_v[i].hash_fields = 0;
    5724                 :          0 :                                 rss_desc_v[i].queue =
    5725                 :          0 :                                         &final_policy->act_cnt[i].queue;
    5726                 :          0 :                                 rss_desc_v[i].queue_num = 1;
    5727                 :          0 :                                 rss_desc[i] = &rss_desc_v[i];
    5728                 :            :                         } else {
    5729                 :          0 :                                 rss_desc[i] = NULL;
    5730                 :            :                         }
    5731                 :            :                 }
    5732                 :            :                 sub_policy = flow_drv_meter_sub_policy_rss_prepare(dev,
    5733                 :            :                                                 flow, policy, rss_desc);
    5734                 :            :         } else {
    5735                 :            :                 enum mlx5_meter_domain mtr_domain =
    5736         [ #  # ]:          0 :                         attr->transfer ? MLX5_MTR_DOMAIN_TRANSFER :
    5737                 :          0 :                                 (attr->egress ? MLX5_MTR_DOMAIN_EGRESS :
    5738                 :            :                                                 MLX5_MTR_DOMAIN_INGRESS);
    5739                 :          0 :                 sub_policy = policy->sub_policys[mtr_domain][0];
    5740                 :            :         }
    5741         [ #  # ]:          0 :         if (!sub_policy)
    5742                 :          0 :                 rte_flow_error_set(error, EINVAL,
    5743                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5744                 :            :                                    "Failed to get meter sub-policy.");
    5745                 :          0 : exit:
    5746                 :          0 :         return sub_policy;
    5747                 :            : }
    5748                 :            : 
    5749                 :            : /**
    5750                 :            :  * Split the meter flow.
    5751                 :            :  *
    5752                 :            :  * As meter flow will split to three sub flow, other than meter
    5753                 :            :  * action, the other actions make sense to only meter accepts
    5754                 :            :  * the packet. If it need to be dropped, no other additional
    5755                 :            :  * actions should be take.
    5756                 :            :  *
    5757                 :            :  * One kind of special action which decapsulates the L3 tunnel
    5758                 :            :  * header will be in the prefix sub flow, as not to take the
    5759                 :            :  * L3 tunnel header into account.
    5760                 :            :  *
    5761                 :            :  * @param[in] dev
    5762                 :            :  *   Pointer to Ethernet device.
    5763                 :            :  * @param[in] flow
    5764                 :            :  *   Parent flow structure pointer.
    5765                 :            :  * @param wks
    5766                 :            :  *   Pointer to thread flow work space.
    5767                 :            :  * @param[in] attr
    5768                 :            :  *   Flow rule attributes.
    5769                 :            :  * @param[in] items
    5770                 :            :  *   Pattern specification (list terminated by the END pattern item).
    5771                 :            :  * @param[out] sfx_items
    5772                 :            :  *   Suffix flow match items (list terminated by the END pattern item).
    5773                 :            :  * @param[in] actions
    5774                 :            :  *   Associated actions (list terminated by the END action).
    5775                 :            :  * @param[out] actions_sfx
    5776                 :            :  *   Suffix flow actions.
    5777                 :            :  * @param[out] actions_pre
    5778                 :            :  *   Prefix flow actions.
    5779                 :            :  * @param[out] mtr_flow_id
    5780                 :            :  *   Pointer to meter flow id.
    5781                 :            :  * @param[out] error
    5782                 :            :  *   Perform verbose error reporting if not NULL.
    5783                 :            :  *
    5784                 :            :  * @return
    5785                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5786                 :            :  */
    5787                 :            : static int
    5788                 :          0 : flow_meter_split_prep(struct rte_eth_dev *dev,
    5789                 :            :                       struct rte_flow *flow,
    5790                 :            :                       struct mlx5_flow_workspace *wks,
    5791                 :            :                       const struct rte_flow_attr *attr,
    5792                 :            :                       const struct rte_flow_item items[],
    5793                 :            :                       struct rte_flow_item sfx_items[],
    5794                 :            :                       const struct rte_flow_action actions[],
    5795                 :            :                       struct rte_flow_action actions_sfx[],
    5796                 :            :                       struct rte_flow_action actions_pre[],
    5797                 :            :                       uint32_t *mtr_flow_id,
    5798                 :            :                       struct rte_flow_error *error)
    5799                 :            : {
    5800                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5801                 :          0 :         struct mlx5_flow_meter_info *fm = wks->fm;
    5802                 :            :         struct rte_flow_action *tag_action = NULL;
    5803                 :            :         struct rte_flow_item *tag_item;
    5804                 :            :         struct mlx5_rte_flow_action_set_tag *set_tag;
    5805                 :            :         const struct rte_flow_action_raw_encap *raw_encap;
    5806                 :            :         const struct rte_flow_action_raw_decap *raw_decap;
    5807                 :            :         struct mlx5_rte_flow_item_tag *tag_item_spec;
    5808                 :            :         struct mlx5_rte_flow_item_tag *tag_item_mask;
    5809                 :          0 :         uint32_t tag_id = 0;
    5810                 :            :         bool vlan_actions;
    5811                 :            :         struct rte_flow_item *orig_sfx_items = sfx_items;
    5812                 :            :         const struct rte_flow_item *orig_items = items;
    5813                 :            :         struct rte_flow_action *hw_mtr_action;
    5814                 :            :         struct rte_flow_action *action_pre_head = NULL;
    5815                 :          0 :         uint16_t flow_src_port = priv->representor_id;
    5816                 :            :         bool mtr_first;
    5817                 :          0 :         uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
    5818         [ #  # ]:          0 :         uint8_t mtr_reg_bits = priv->mtr_reg_share ?
    5819                 :            :                                 MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
    5820                 :            :         uint32_t flow_id = 0;
    5821                 :            :         uint32_t flow_id_reversed = 0;
    5822                 :            :         uint8_t flow_id_bits = 0;
    5823                 :            :         bool after_meter = false;
    5824                 :            :         int shift;
    5825                 :            : 
    5826                 :            :         /* Prepare the suffix subflow items. */
    5827                 :          0 :         tag_item = sfx_items++;
    5828                 :          0 :         tag_item->type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG;
    5829         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    5830                 :            :                 int item_type = items->type;
    5831                 :            : 
    5832      [ #  #  # ]:          0 :                 switch (item_type) {
    5833                 :          0 :                 case RTE_FLOW_ITEM_TYPE_PORT_ID:
    5834                 :            :                 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
    5835                 :            :                 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
    5836         [ #  # ]:          0 :                         if (mlx5_flow_get_item_vport_id(dev, items, &flow_src_port, NULL, error))
    5837                 :          0 :                                 return -rte_errno;
    5838   [ #  #  #  # ]:          0 :                         if (!fm->def_policy && wks->policy->hierarchy_match_port &&
    5839         [ #  # ]:          0 :                             flow_src_port != priv->representor_id) {
    5840         [ #  # ]:          0 :                                 if (flow_drv_mtr_hierarchy_rule_create(dev,
    5841                 :            :                                                                 flow, fm,
    5842                 :            :                                                                 flow_src_port,
    5843                 :            :                                                                 items,
    5844                 :            :                                                                 error))
    5845                 :          0 :                                         return -rte_errno;
    5846                 :            :                         }
    5847                 :            :                         memcpy(sfx_items, items, sizeof(*sfx_items));
    5848                 :          0 :                         sfx_items++;
    5849                 :          0 :                         break;
    5850                 :            :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    5851                 :            :                         /*
    5852                 :            :                          * Copy VLAN items in case VLAN actions are performed.
    5853                 :            :                          * If there are no VLAN actions, these items will be VOID.
    5854                 :            :                          */
    5855                 :            :                         memcpy(sfx_items, items, sizeof(*sfx_items));
    5856                 :          0 :                         sfx_items->type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_VLAN;
    5857                 :          0 :                         sfx_items++;
    5858                 :          0 :                         break;
    5859                 :            :                 default:
    5860                 :            :                         break;
    5861                 :            :                 }
    5862                 :            :         }
    5863                 :          0 :         sfx_items->type = RTE_FLOW_ITEM_TYPE_END;
    5864                 :          0 :         sfx_items++;
    5865         [ #  # ]:          0 :         mtr_first = priv->sh->meter_aso_en &&
    5866   [ #  #  #  #  :          0 :                 (attr->egress || (attr->transfer && flow_src_port != UINT16_MAX));
                   #  # ]
    5867                 :            :         /* For ASO meter, meter must be before tag in TX direction. */
    5868         [ #  # ]:          0 :         if (mtr_first) {
    5869                 :          0 :                 action_pre_head = actions_pre++;
    5870                 :            :                 /* Leave space for tag action. */
    5871                 :          0 :                 tag_action = actions_pre++;
    5872                 :            :         }
    5873                 :            :         /* Prepare the actions for prefix and suffix flow. */
    5874                 :            :         vlan_actions = false;
    5875         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    5876                 :            :                 struct rte_flow_action *action_cur = NULL;
    5877                 :            : 
    5878   [ #  #  #  #  :          0 :                 switch (actions->type) {
                #  #  # ]
    5879                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    5880         [ #  # ]:          0 :                         if (mtr_first) {
    5881                 :            :                                 action_cur = action_pre_head;
    5882                 :            :                         } else {
    5883                 :            :                                 /* Leave space for tag action. */
    5884                 :          0 :                                 tag_action = actions_pre++;
    5885                 :          0 :                                 action_cur = actions_pre++;
    5886                 :            :                         }
    5887                 :            :                         after_meter = true;
    5888                 :            :                         break;
    5889                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    5890                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    5891                 :          0 :                         action_cur = actions_pre++;
    5892                 :          0 :                         break;
    5893                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    5894                 :          0 :                         raw_encap = actions->conf;
    5895         [ #  # ]:          0 :                         if (raw_encap->size < MLX5_ENCAPSULATION_DECISION_SIZE)
    5896                 :          0 :                                 action_cur = actions_pre++;
    5897                 :            :                         break;
    5898                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    5899                 :          0 :                         raw_decap = actions->conf;
    5900         [ #  # ]:          0 :                         if (raw_decap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
    5901                 :          0 :                                 action_cur = actions_pre++;
    5902                 :            :                         break;
    5903                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    5904                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    5905                 :            :                         vlan_actions = true;
    5906                 :          0 :                         break;
    5907                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    5908         [ #  # ]:          0 :                         if (fm->def_policy)
    5909                 :            :                                 action_cur = after_meter ?
    5910         [ #  # ]:          0 :                                                 actions_sfx++ : actions_pre++;
    5911                 :            :                         break;
    5912                 :            :                 default:
    5913                 :            :                         break;
    5914                 :            :                 }
    5915         [ #  # ]:          0 :                 if (!action_cur)
    5916                 :          0 :                         action_cur = (fm->def_policy) ?
    5917         [ #  # ]:          0 :                                         actions_sfx++ : actions_pre++;
    5918                 :            :                 memcpy(action_cur, actions, sizeof(struct rte_flow_action));
    5919                 :            :         }
    5920                 :            :         /* If there are no VLAN actions, convert VLAN items to VOID in suffix flow items. */
    5921         [ #  # ]:          0 :         if (!vlan_actions) {
    5922                 :            :                 struct rte_flow_item *it = orig_sfx_items;
    5923                 :            : 
    5924         [ #  # ]:          0 :                 for (; it->type != RTE_FLOW_ITEM_TYPE_END; it++)
    5925         [ #  # ]:          0 :                         if (it->type == (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
    5926                 :          0 :                                 it->type = RTE_FLOW_ITEM_TYPE_VOID;
    5927                 :            :         }
    5928                 :            :         /* Add end action to the actions. */
    5929                 :          0 :         actions_sfx->type = RTE_FLOW_ACTION_TYPE_END;
    5930         [ #  # ]:          0 :         if (priv->sh->meter_aso_en) {
    5931                 :            :                 /**
    5932                 :            :                  * For ASO meter, need to add an extra jump action explicitly,
    5933                 :            :                  * to jump from meter to policer table.
    5934                 :            :                  */
    5935                 :            :                 struct mlx5_flow_meter_sub_policy *sub_policy;
    5936                 :            :                 struct mlx5_flow_tbl_data_entry *tbl_data;
    5937                 :            : 
    5938         [ #  # ]:          0 :                 if (!fm->def_policy) {
    5939                 :          0 :                         sub_policy = get_meter_sub_policy(dev, flow, wks,
    5940                 :            :                                                           attr, orig_items,
    5941                 :            :                                                           error);
    5942         [ #  # ]:          0 :                         if (!sub_policy)
    5943                 :          0 :                                 return -rte_errno;
    5944                 :            :                 } else {
    5945                 :            :                         enum mlx5_meter_domain mtr_domain =
    5946         [ #  # ]:          0 :                         attr->transfer ? MLX5_MTR_DOMAIN_TRANSFER :
    5947                 :          0 :                                 (attr->egress ? MLX5_MTR_DOMAIN_EGRESS :
    5948                 :            :                                                 MLX5_MTR_DOMAIN_INGRESS);
    5949                 :            : 
    5950                 :          0 :                         sub_policy =
    5951                 :          0 :                         &priv->sh->mtrmng->def_policy[mtr_domain]->sub_policy;
    5952                 :            :                 }
    5953                 :          0 :                 tbl_data = container_of(sub_policy->tbl_rsc,
    5954                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
    5955                 :          0 :                 hw_mtr_action = actions_pre++;
    5956                 :          0 :                 hw_mtr_action->type = (enum rte_flow_action_type)
    5957                 :            :                                       MLX5_RTE_FLOW_ACTION_TYPE_JUMP;
    5958                 :          0 :                 hw_mtr_action->conf = tbl_data->jump.action;
    5959                 :            :         }
    5960                 :          0 :         actions_pre->type = RTE_FLOW_ACTION_TYPE_END;
    5961                 :          0 :         actions_pre++;
    5962         [ #  # ]:          0 :         if (!tag_action)
    5963                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
    5964                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5965                 :            :                                           NULL, "No tag action space.");
    5966         [ #  # ]:          0 :         if (!mtr_flow_id) {
    5967                 :          0 :                 tag_action->type = RTE_FLOW_ACTION_TYPE_VOID;
    5968                 :          0 :                 goto exit;
    5969                 :            :         }
    5970                 :            :         /* Only default-policy Meter creates mtr flow id. */
    5971         [ #  # ]:          0 :         if (fm->def_policy) {
    5972                 :          0 :                 mlx5_ipool_malloc(fm->flow_ipool, &tag_id);
    5973         [ #  # ]:          0 :                 if (!tag_id)
    5974                 :          0 :                         return rte_flow_error_set(error, ENOMEM,
    5975                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5976                 :            :                                         "Failed to allocate meter flow id.");
    5977                 :          0 :                 flow_id = tag_id - 1;
    5978         [ #  # ]:          0 :                 flow_id_bits = (!flow_id) ? 1 :
    5979                 :          0 :                                 (MLX5_REG_BITS - rte_clz32(flow_id));
    5980         [ #  # ]:          0 :                 if ((flow_id_bits + priv->sh->mtrmng->max_mtr_bits) >
    5981                 :            :                     mtr_reg_bits) {
    5982                 :          0 :                         mlx5_ipool_free(fm->flow_ipool, tag_id);
    5983                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5984                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5985                 :            :                                         "Meter flow id exceeds max limit.");
    5986                 :            :                 }
    5987         [ #  # ]:          0 :                 if (flow_id_bits > priv->sh->mtrmng->max_mtr_flow_bits)
    5988                 :          0 :                         priv->sh->mtrmng->max_mtr_flow_bits = flow_id_bits;
    5989                 :            :         }
    5990                 :            :         /* Build tag actions and items for meter_id/meter flow_id. */
    5991                 :            :         set_tag = (struct mlx5_rte_flow_action_set_tag *)actions_pre;
    5992                 :            :         tag_item_spec = (struct mlx5_rte_flow_item_tag *)sfx_items;
    5993                 :          0 :         tag_item_mask = tag_item_spec + 1;
    5994                 :            :         /* Both flow_id and meter_id share the same register. */
    5995                 :          0 :         *set_tag = (struct mlx5_rte_flow_action_set_tag) {
    5996                 :          0 :                 .id = (enum modify_reg)mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
    5997                 :            :                                                             0, error),
    5998                 :            :                 .offset = mtr_id_offset,
    5999                 :            :                 .length = mtr_reg_bits,
    6000                 :          0 :                 .data = flow->meter,
    6001                 :            :         };
    6002                 :            :         /*
    6003                 :            :          * The color Reg bits used by flow_id are growing from
    6004                 :            :          * msb to lsb, so must do bit reverse for flow_id val in RegC.
    6005                 :            :          */
    6006         [ #  # ]:          0 :         for (shift = 0; shift < flow_id_bits; shift++)
    6007                 :          0 :                 flow_id_reversed = (flow_id_reversed << 1) |
    6008                 :          0 :                                 ((flow_id >> shift) & 0x1);
    6009                 :          0 :         set_tag->data |=
    6010                 :          0 :                 flow_id_reversed << (mtr_reg_bits - flow_id_bits);
    6011                 :          0 :         tag_item_spec->id = set_tag->id;
    6012                 :          0 :         tag_item_spec->data = set_tag->data << mtr_id_offset;
    6013                 :          0 :         tag_item_mask->data = UINT32_MAX << mtr_id_offset;
    6014                 :          0 :         tag_action->type = (enum rte_flow_action_type)
    6015                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_TAG;
    6016                 :          0 :         tag_action->conf = set_tag;
    6017                 :          0 :         tag_item->spec = tag_item_spec;
    6018                 :          0 :         tag_item->last = NULL;
    6019                 :          0 :         tag_item->mask = tag_item_mask;
    6020                 :          0 : exit:
    6021         [ #  # ]:          0 :         if (mtr_flow_id)
    6022                 :          0 :                 *mtr_flow_id = tag_id;
    6023                 :            :         return 0;
    6024                 :            : }
    6025                 :            : 
    6026                 :            : /**
    6027                 :            :  * Split action list having QUEUE/RSS for metadata register copy.
    6028                 :            :  *
    6029                 :            :  * Once Q/RSS action is detected in user's action list, the flow action
    6030                 :            :  * should be split in order to copy metadata registers, which will happen in
    6031                 :            :  * RX_CP_TBL like,
    6032                 :            :  *   - CQE->flow_tag := reg_c[1] (MARK)
    6033                 :            :  *   - CQE->flow_table_metadata (reg_b) := reg_c[0] (META)
    6034                 :            :  * The Q/RSS action will be performed on RX_ACT_TBL after passing by RX_CP_TBL.
    6035                 :            :  * This is because the last action of each flow must be a terminal action
    6036                 :            :  * (QUEUE, RSS or DROP).
    6037                 :            :  *
    6038                 :            :  * Flow ID must be allocated to identify actions in the RX_ACT_TBL and it is
    6039                 :            :  * stored and kept in the mlx5_flow structure per each sub_flow.
    6040                 :            :  *
    6041                 :            :  * The Q/RSS action is replaced with,
    6042                 :            :  *   - SET_TAG, setting the allocated flow ID to reg_c[2].
    6043                 :            :  * And the following JUMP action is added at the end,
    6044                 :            :  *   - JUMP, to RX_CP_TBL.
    6045                 :            :  *
    6046                 :            :  * A flow to perform remained Q/RSS action will be created in RX_ACT_TBL by
    6047                 :            :  * flow_create_split_metadata() routine. The flow will look like,
    6048                 :            :  *   - If flow ID matches (reg_c[2]), perform Q/RSS.
    6049                 :            :  *
    6050                 :            :  * @param dev
    6051                 :            :  *   Pointer to Ethernet device.
    6052                 :            :  * @param[out] split_actions
    6053                 :            :  *   Pointer to store split actions to jump to CP_TBL.
    6054                 :            :  * @param[in] actions
    6055                 :            :  *   Pointer to the list of original flow actions.
    6056                 :            :  * @param[in] qrss
    6057                 :            :  *   Pointer to the Q/RSS action.
    6058                 :            :  * @param[in] actions_n
    6059                 :            :  *   Number of original actions.
    6060                 :            :  * @param[in] mtr_sfx
    6061                 :            :  *   Check if it is in meter suffix table.
    6062                 :            :  * @param[out] error
    6063                 :            :  *   Perform verbose error reporting if not NULL.
    6064                 :            :  *
    6065                 :            :  * @return
    6066                 :            :  *   non-zero unique flow_id on success, otherwise 0 and
    6067                 :            :  *   error/rte_error are set.
    6068                 :            :  */
    6069                 :            : static uint32_t
    6070                 :          0 : flow_mreg_split_qrss_prep(struct rte_eth_dev *dev,
    6071                 :            :                           struct rte_flow_action *split_actions,
    6072                 :            :                           const struct rte_flow_action *actions,
    6073                 :            :                           const struct rte_flow_action *qrss,
    6074                 :            :                           int actions_n, int mtr_sfx,
    6075                 :            :                           struct rte_flow_error *error)
    6076                 :            : {
    6077                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6078                 :            :         struct mlx5_rte_flow_action_set_tag *set_tag;
    6079                 :            :         struct rte_flow_action_jump *jump;
    6080                 :          0 :         const int qrss_idx = qrss - actions;
    6081                 :          0 :         uint32_t flow_id = 0;
    6082                 :            :         int ret = 0;
    6083                 :            : 
    6084                 :            :         /*
    6085                 :            :          * Given actions will be split
    6086                 :            :          * - Replace QUEUE/RSS action with SET_TAG to set flow ID.
    6087                 :            :          * - Add jump to mreg CP_TBL.
    6088                 :            :          * As a result, there will be one more action.
    6089                 :            :          */
    6090         [ #  # ]:          0 :         memcpy(split_actions, actions, sizeof(*split_actions) * actions_n);
    6091                 :            :         /* Count MLX5_RTE_FLOW_ACTION_TYPE_TAG. */
    6092                 :          0 :         ++actions_n;
    6093                 :          0 :         set_tag = (void *)(split_actions + actions_n);
    6094                 :            :         /*
    6095                 :            :          * If we are not the meter suffix flow, add the tag action.
    6096                 :            :          * Since meter suffix flow already has the tag added.
    6097                 :            :          */
    6098         [ #  # ]:          0 :         if (!mtr_sfx) {
    6099                 :            :                 /*
    6100                 :            :                  * Allocate the new subflow ID. This one is unique within
    6101                 :            :                  * device and not shared with representors. Otherwise,
    6102                 :            :                  * we would have to resolve multi-thread access synch
    6103                 :            :                  * issue. Each flow on the shared device is appended
    6104                 :            :                  * with source vport identifier, so the resulting
    6105                 :            :                  * flows will be unique in the shared (by master and
    6106                 :            :                  * representors) domain even if they have coinciding
    6107                 :            :                  * IDs.
    6108                 :            :                  */
    6109                 :          0 :                 mlx5_ipool_malloc(priv->sh->ipool
    6110                 :            :                                   [MLX5_IPOOL_RSS_EXPANTION_FLOW_ID], &flow_id);
    6111         [ #  # ]:          0 :                 if (!flow_id)
    6112                 :          0 :                         return rte_flow_error_set(error, ENOMEM,
    6113                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6114                 :            :                                                   NULL, "can't allocate id "
    6115                 :            :                                                   "for split Q/RSS subflow");
    6116                 :            :                 /* Internal SET_TAG action to set flow ID. */
    6117                 :          0 :                 *set_tag = (struct mlx5_rte_flow_action_set_tag){
    6118                 :            :                         .data = flow_id,
    6119                 :            :                 };
    6120                 :          0 :                 ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0, error);
    6121         [ #  # ]:          0 :                 if (ret < 0)
    6122                 :          0 :                         return ret;
    6123                 :          0 :                 set_tag->id = ret;
    6124                 :            :                 /* Construct new actions array. */
    6125                 :            :                 /* Replace QUEUE/RSS action. */
    6126                 :          0 :                 split_actions[qrss_idx] = (struct rte_flow_action){
    6127                 :            :                         .type = (enum rte_flow_action_type)
    6128                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_TAG,
    6129                 :            :                         .conf = set_tag,
    6130                 :            :                 };
    6131                 :            :         } else {
    6132                 :            :                 /*
    6133                 :            :                  * If we are the suffix flow of meter, tag already exist.
    6134                 :            :                  * Set the QUEUE/RSS action to void.
    6135                 :            :                  */
    6136                 :          0 :                 split_actions[qrss_idx].type = RTE_FLOW_ACTION_TYPE_VOID;
    6137                 :            :         }
    6138                 :            :         /* JUMP action to jump to mreg copy table (CP_TBL). */
    6139                 :          0 :         jump = (void *)(set_tag + 1);
    6140                 :          0 :         *jump = (struct rte_flow_action_jump){
    6141                 :            :                 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP,
    6142                 :            :         };
    6143                 :          0 :         split_actions[actions_n - 2] = (struct rte_flow_action){
    6144                 :            :                 .type = RTE_FLOW_ACTION_TYPE_JUMP,
    6145                 :            :                 .conf = jump,
    6146                 :            :         };
    6147                 :          0 :         split_actions[actions_n - 1] = (struct rte_flow_action){
    6148                 :            :                 .type = RTE_FLOW_ACTION_TYPE_END,
    6149                 :            :         };
    6150                 :          0 :         return flow_id;
    6151                 :            : }
    6152                 :            : 
    6153                 :            : /**
    6154                 :            :  * Extend the given action list for Tx metadata copy.
    6155                 :            :  *
    6156                 :            :  * Copy the given action list to the ext_actions and add flow metadata register
    6157                 :            :  * copy action in order to copy reg_a set by WQE to reg_c[0].
    6158                 :            :  *
    6159                 :            :  * @param[out] ext_actions
    6160                 :            :  *   Pointer to the extended action list.
    6161                 :            :  * @param[in] actions
    6162                 :            :  *   Pointer to the list of actions.
    6163                 :            :  * @param[in] actions_n
    6164                 :            :  *   Number of actions in the list.
    6165                 :            :  * @param[out] error
    6166                 :            :  *   Perform verbose error reporting if not NULL.
    6167                 :            :  * @param[in] encap_idx
    6168                 :            :  *   The encap action index.
    6169                 :            :  *
    6170                 :            :  * @return
    6171                 :            :  *   0 on success, negative value otherwise
    6172                 :            :  */
    6173                 :            : static int
    6174                 :          0 : flow_mreg_tx_copy_prep(struct rte_eth_dev *dev,
    6175                 :            :                        struct rte_flow_action *ext_actions,
    6176                 :            :                        const struct rte_flow_action *actions,
    6177                 :            :                        int actions_n, struct rte_flow_error *error,
    6178                 :            :                        int encap_idx)
    6179                 :            : {
    6180                 :          0 :         struct mlx5_flow_action_copy_mreg *cp_mreg =
    6181                 :            :                 (struct mlx5_flow_action_copy_mreg *)
    6182                 :          0 :                         (ext_actions + actions_n + 1);
    6183                 :            :         int ret;
    6184                 :            : 
    6185                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_RX, 0, error);
    6186         [ #  # ]:          0 :         if (ret < 0)
    6187                 :            :                 return ret;
    6188                 :          0 :         cp_mreg->dst = ret;
    6189                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_TX, 0, error);
    6190         [ #  # ]:          0 :         if (ret < 0)
    6191                 :            :                 return ret;
    6192                 :          0 :         cp_mreg->src = ret;
    6193         [ #  # ]:          0 :         if (encap_idx != 0)
    6194                 :          0 :                 memcpy(ext_actions, actions, sizeof(*ext_actions) * encap_idx);
    6195         [ #  # ]:          0 :         if (encap_idx == actions_n - 1) {
    6196                 :          0 :                 ext_actions[actions_n - 1] = (struct rte_flow_action){
    6197                 :            :                         .type = (enum rte_flow_action_type)
    6198                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
    6199                 :            :                         .conf = cp_mreg,
    6200                 :            :                 };
    6201                 :          0 :                 ext_actions[actions_n] = (struct rte_flow_action){
    6202                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
    6203                 :            :                 };
    6204                 :            :         } else {
    6205                 :          0 :                 ext_actions[encap_idx] = (struct rte_flow_action){
    6206                 :            :                         .type = (enum rte_flow_action_type)
    6207                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
    6208                 :            :                         .conf = cp_mreg,
    6209                 :            :                 };
    6210                 :          0 :                 memcpy(ext_actions + encap_idx + 1, actions + encap_idx,
    6211                 :          0 :                                 sizeof(*ext_actions) * (actions_n - encap_idx));
    6212                 :            :         }
    6213                 :            :         return 0;
    6214                 :            : }
    6215                 :            : 
    6216                 :            : /**
    6217                 :            :  * Check the match action from the action list.
    6218                 :            :  *
    6219                 :            :  * @param[in] actions
    6220                 :            :  *   Pointer to the list of actions.
    6221                 :            :  * @param[in] attr
    6222                 :            :  *   Flow rule attributes.
    6223                 :            :  * @param[in] action
    6224                 :            :  *   The action to be check if exist.
    6225                 :            :  * @param[out] match_action_pos
    6226                 :            :  *   Pointer to the position of the matched action if exists, otherwise is -1.
    6227                 :            :  * @param[out] qrss_action_pos
    6228                 :            :  *   Pointer to the position of the Queue/RSS action if exists, otherwise is -1.
    6229                 :            :  * @param[out] modify_after_mirror
    6230                 :            :  *   Pointer to the flag of modify action after FDB mirroring.
    6231                 :            :  *
    6232                 :            :  * @return
    6233                 :            :  *   > 0 the total number of actions.
    6234                 :            :  *   0 if not found match action in action list.
    6235                 :            :  */
    6236                 :            : static int
    6237                 :          0 : flow_check_match_action(const struct rte_flow_action actions[],
    6238                 :            :                         const struct rte_flow_attr *attr,
    6239                 :            :                         enum rte_flow_action_type action,
    6240                 :            :                         int *match_action_pos, int *qrss_action_pos,
    6241                 :            :                         int *modify_after_mirror)
    6242                 :            : {
    6243                 :            :         const struct rte_flow_action_sample *sample;
    6244                 :            :         const struct rte_flow_action_raw_decap *decap;
    6245                 :            :         const struct rte_flow_action *action_cur = NULL;
    6246                 :            :         int actions_n = 0;
    6247                 :            :         uint32_t ratio = 0;
    6248                 :            :         int sub_type = 0;
    6249                 :            :         int flag = 0;
    6250                 :            :         int fdb_mirror = 0;
    6251                 :            : 
    6252                 :          0 :         *match_action_pos = -1;
    6253                 :          0 :         *qrss_action_pos = -1;
    6254         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    6255         [ #  # ]:          0 :                 if (actions->type == action) {
    6256                 :            :                         flag = 1;
    6257                 :          0 :                         *match_action_pos = actions_n;
    6258                 :            :                 }
    6259   [ #  #  #  #  :          0 :                 switch (actions->type) {
                      # ]
    6260                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    6261                 :            :                 case RTE_FLOW_ACTION_TYPE_RSS:
    6262                 :          0 :                         *qrss_action_pos = actions_n;
    6263                 :          0 :                         break;
    6264                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
    6265                 :          0 :                         sample = actions->conf;
    6266                 :          0 :                         ratio = sample->ratio;
    6267                 :          0 :                         sub_type = ((const struct rte_flow_action *)
    6268                 :          0 :                                         (sample->actions))->type;
    6269   [ #  #  #  #  :          0 :                         if (ratio == 1 && attr->transfer &&
                   #  # ]
    6270                 :            :                             sub_type != RTE_FLOW_ACTION_TYPE_END)
    6271                 :            :                                 fdb_mirror = 1;
    6272                 :            :                         break;
    6273                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
    6274                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    6275                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
    6276                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
    6277                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
    6278                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
    6279                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
    6280                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    6281                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
    6282                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
    6283                 :            :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
    6284                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
    6285                 :            :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
    6286                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
    6287                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
    6288                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
    6289                 :            :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    6290                 :            :                 case RTE_FLOW_ACTION_TYPE_MARK:
    6291                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_META:
    6292                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
    6293                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    6294                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    6295                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    6296                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    6297                 :            :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    6298                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    6299                 :            :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    6300                 :            :                 case RTE_FLOW_ACTION_TYPE_METER:
    6301         [ #  # ]:          0 :                         if (fdb_mirror)
    6302                 :          0 :                                 *modify_after_mirror = 1;
    6303                 :            :                         break;
    6304                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    6305                 :          0 :                         decap = actions->conf;
    6306                 :            :                         action_cur = actions;
    6307         [ #  # ]:          0 :                         while ((++action_cur)->type == RTE_FLOW_ACTION_TYPE_VOID)
    6308                 :            :                                 ;
    6309         [ #  # ]:          0 :                         if (action_cur->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    6310                 :          0 :                                 const struct rte_flow_action_raw_encap *encap =
    6311                 :            :                                                                 action_cur->conf;
    6312         [ #  # ]:          0 :                                 if (decap->size <=
    6313                 :          0 :                                         MLX5_ENCAPSULATION_DECISION_SIZE &&
    6314         [ #  # ]:          0 :                                     encap->size >
    6315                 :            :                                         MLX5_ENCAPSULATION_DECISION_SIZE)
    6316                 :            :                                         /* L3 encap. */
    6317                 :            :                                         break;
    6318                 :            :                         }
    6319         [ #  # ]:          0 :                         if (fdb_mirror)
    6320                 :          0 :                                 *modify_after_mirror = 1;
    6321                 :            :                         break;
    6322                 :            :                 default:
    6323                 :            :                         break;
    6324                 :            :                 }
    6325                 :          0 :                 actions_n++;
    6326                 :            :         }
    6327   [ #  #  #  # ]:          0 :         if (flag && fdb_mirror && !*modify_after_mirror) {
    6328                 :            :                 /* FDB mirroring uses the destination array to implement
    6329                 :            :                  * instead of FLOW_SAMPLER object.
    6330                 :            :                  */
    6331         [ #  # ]:          0 :                 if (sub_type != RTE_FLOW_ACTION_TYPE_END)
    6332                 :            :                         flag = 0;
    6333                 :            :         }
    6334                 :            :         /* Count RTE_FLOW_ACTION_TYPE_END. */
    6335         [ #  # ]:          0 :         return flag ? actions_n + 1 : 0;
    6336                 :            : }
    6337                 :            : 
    6338                 :            : #define SAMPLE_SUFFIX_ITEM 3
    6339                 :            : 
    6340                 :            : /**
    6341                 :            :  * Split the sample flow.
    6342                 :            :  *
    6343                 :            :  * As sample flow will split to two sub flow, sample flow with
    6344                 :            :  * sample action, the other actions will move to new suffix flow.
    6345                 :            :  *
    6346                 :            :  * Also add unique tag id with tag action in the sample flow,
    6347                 :            :  * the same tag id will be as match in the suffix flow.
    6348                 :            :  *
    6349                 :            :  * @param dev
    6350                 :            :  *   Pointer to Ethernet device.
    6351                 :            :  * @param[in] add_tag
    6352                 :            :  *   Add extra tag action flag.
    6353                 :            :  * @param[out] sfx_items
    6354                 :            :  *   Suffix flow match items (list terminated by the END pattern item).
    6355                 :            :  * @param[in] actions
    6356                 :            :  *   Associated actions (list terminated by the END action).
    6357                 :            :  * @param[out] actions_sfx
    6358                 :            :  *   Suffix flow actions.
    6359                 :            :  * @param[out] actions_pre
    6360                 :            :  *   Prefix flow actions.
    6361                 :            :  * @param[in] actions_n
    6362                 :            :  *  The total number of actions.
    6363                 :            :  * @param[in] sample_action_pos
    6364                 :            :  *   The sample action position.
    6365                 :            :  * @param[in] qrss_action_pos
    6366                 :            :  *   The Queue/RSS action position.
    6367                 :            :  * @param[in] jump_table
    6368                 :            :  *   Add extra jump action flag.
    6369                 :            :  * @param[out] error
    6370                 :            :  *   Perform verbose error reporting if not NULL.
    6371                 :            :  *
    6372                 :            :  * @return
    6373                 :            :  *   0 on success, or unique flow_id, a negative errno value
    6374                 :            :  *   otherwise and rte_errno is set.
    6375                 :            :  */
    6376                 :            : static int
    6377                 :          0 : flow_sample_split_prep(struct rte_eth_dev *dev,
    6378                 :            :                        int add_tag,
    6379                 :            :                        const struct rte_flow_item items[],
    6380                 :            :                        struct rte_flow_item sfx_items[],
    6381                 :            :                        const struct rte_flow_action actions[],
    6382                 :            :                        struct rte_flow_action actions_sfx[],
    6383                 :            :                        struct rte_flow_action actions_pre[],
    6384                 :            :                        int actions_n,
    6385                 :            :                        int sample_action_pos,
    6386                 :            :                        int qrss_action_pos,
    6387                 :            :                        int jump_table,
    6388                 :            :                        struct rte_flow_error *error)
    6389                 :            : {
    6390                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6391                 :            :         struct mlx5_rte_flow_action_set_tag *set_tag;
    6392                 :            :         struct mlx5_rte_flow_item_tag *tag_spec;
    6393                 :            :         struct mlx5_rte_flow_item_tag *tag_mask;
    6394                 :            :         struct rte_flow_action_jump *jump_action;
    6395                 :          0 :         uint32_t tag_id = 0;
    6396                 :            :         int append_index = 0;
    6397                 :            :         int set_tag_idx = -1;
    6398                 :            :         int index;
    6399                 :            :         int ret;
    6400                 :            : 
    6401         [ #  # ]:          0 :         if (sample_action_pos < 0)
    6402                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6403                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    6404                 :            :                                           NULL, "invalid position of sample "
    6405                 :            :                                           "action in list");
    6406                 :            :         /* Prepare the actions for prefix and suffix flow. */
    6407         [ #  # ]:          0 :         if (add_tag) {
    6408                 :            :                 /* Update the new added tag action index preceding
    6409                 :            :                  * the PUSH_VLAN or ENCAP action.
    6410                 :            :                  */
    6411                 :            :                 const struct rte_flow_action_raw_encap *raw_encap;
    6412                 :            :                 const struct rte_flow_action *action = actions;
    6413                 :            :                 int encap_idx;
    6414                 :            :                 int action_idx = 0;
    6415                 :            :                 int raw_decap_idx = -1;
    6416                 :            :                 int push_vlan_idx = -1;
    6417         [ #  # ]:          0 :                 for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
    6418   [ #  #  #  #  :          0 :                         switch (action->type) {
                      # ]
    6419                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    6420                 :            :                                 raw_decap_idx = action_idx;
    6421                 :          0 :                                 break;
    6422                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    6423                 :          0 :                                 raw_encap = action->conf;
    6424         [ #  # ]:          0 :                                 if (raw_encap->size >
    6425                 :            :                                         MLX5_ENCAPSULATION_DECISION_SIZE) {
    6426                 :            :                                         encap_idx = raw_decap_idx != -1 ?
    6427         [ #  # ]:          0 :                                                     raw_decap_idx : action_idx;
    6428                 :          0 :                                         if (encap_idx < sample_action_pos &&
    6429         [ #  # ]:          0 :                                             push_vlan_idx == -1)
    6430                 :            :                                                 set_tag_idx = encap_idx;
    6431                 :            :                                 }
    6432                 :            :                                 break;
    6433                 :          0 :                         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    6434                 :            :                         case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    6435                 :            :                                 encap_idx = action_idx;
    6436                 :          0 :                                 if (encap_idx < sample_action_pos &&
    6437         [ #  # ]:          0 :                                     push_vlan_idx == -1)
    6438                 :            :                                         set_tag_idx = encap_idx;
    6439                 :            :                                 break;
    6440                 :          0 :                         case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    6441                 :            :                         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    6442                 :          0 :                                 if (action_idx < sample_action_pos &&
    6443         [ #  # ]:          0 :                                     push_vlan_idx == -1) {
    6444                 :            :                                         set_tag_idx = action_idx;
    6445                 :            :                                         push_vlan_idx = action_idx;
    6446                 :            :                                 }
    6447                 :            :                                 break;
    6448                 :            :                         default:
    6449                 :            :                                 break;
    6450                 :            :                         }
    6451                 :          0 :                         action_idx++;
    6452                 :            :                 }
    6453                 :            :         }
    6454                 :            :         /* Prepare the actions for prefix and suffix flow. */
    6455         [ #  # ]:          0 :         if (qrss_action_pos >= 0 && qrss_action_pos < sample_action_pos) {
    6456                 :            :                 index = qrss_action_pos;
    6457                 :            :                 /* Put the preceding the Queue/RSS action into prefix flow. */
    6458         [ #  # ]:          0 :                 if (index != 0)
    6459                 :          0 :                         memcpy(actions_pre, actions,
    6460                 :            :                                sizeof(struct rte_flow_action) * index);
    6461                 :            :                 /* Put others preceding the sample action into prefix flow. */
    6462         [ #  # ]:          0 :                 if (sample_action_pos > index + 1)
    6463                 :          0 :                         memcpy(actions_pre + index, actions + index + 1,
    6464                 :            :                                sizeof(struct rte_flow_action) *
    6465                 :          0 :                                (sample_action_pos - index - 1));
    6466                 :          0 :                 index = sample_action_pos - 1;
    6467                 :            :                 /* Put Queue/RSS action into Suffix flow. */
    6468                 :          0 :                 memcpy(actions_sfx, actions + qrss_action_pos,
    6469                 :            :                        sizeof(struct rte_flow_action));
    6470                 :          0 :                 actions_sfx++;
    6471         [ #  # ]:          0 :         } else if (add_tag && set_tag_idx >= 0) {
    6472         [ #  # ]:          0 :                 if (set_tag_idx > 0)
    6473                 :          0 :                         memcpy(actions_pre, actions,
    6474                 :            :                                sizeof(struct rte_flow_action) * set_tag_idx);
    6475                 :          0 :                 memcpy(actions_pre + set_tag_idx + 1, actions + set_tag_idx,
    6476                 :            :                        sizeof(struct rte_flow_action) *
    6477                 :          0 :                        (sample_action_pos - set_tag_idx));
    6478                 :            :                 index = sample_action_pos;
    6479                 :            :         } else {
    6480                 :            :                 index = sample_action_pos;
    6481         [ #  # ]:          0 :                 if (index != 0)
    6482                 :          0 :                         memcpy(actions_pre, actions,
    6483                 :            :                                sizeof(struct rte_flow_action) * index);
    6484                 :            :         }
    6485                 :            :         /* For CX5, add an extra tag action for NIC-RX and E-Switch ingress.
    6486                 :            :          * For CX6DX and above, metadata registers Cx preserve their value,
    6487                 :            :          * add an extra tag action for NIC-RX and E-Switch Domain.
    6488                 :            :          */
    6489         [ #  # ]:          0 :         if (add_tag) {
    6490                 :            :                 /* Prepare the prefix tag action. */
    6491                 :            :                 append_index++;
    6492                 :          0 :                 set_tag = (void *)(actions_pre + actions_n + append_index);
    6493                 :            :                 /* Trust VF/SF on CX5 not supported meter so that the reserved
    6494                 :            :                  * metadata regC is REG_NON, back to use application tag
    6495                 :            :                  * index 0.
    6496                 :            :                  */
    6497         [ #  # ]:          0 :                 if (unlikely(priv->sh->registers.aso_reg == REG_NON))
    6498                 :          0 :                         ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, 0, error);
    6499                 :            :                 else
    6500                 :          0 :                         ret = mlx5_flow_get_reg_id(dev, MLX5_SAMPLE_ID, 0, error);
    6501         [ #  # ]:          0 :                 if (ret < 0)
    6502                 :            :                         return ret;
    6503                 :          0 :                 mlx5_ipool_malloc(priv->sh->ipool
    6504                 :            :                                   [MLX5_IPOOL_RSS_EXPANTION_FLOW_ID], &tag_id);
    6505                 :          0 :                 *set_tag = (struct mlx5_rte_flow_action_set_tag) {
    6506                 :            :                         .id = ret,
    6507                 :            :                         .data = tag_id,
    6508                 :            :                 };
    6509                 :            :                 /* Prepare the suffix subflow items. */
    6510                 :          0 :                 tag_spec = (void *)(sfx_items + SAMPLE_SUFFIX_ITEM);
    6511                 :          0 :                 tag_spec->data = tag_id;
    6512                 :          0 :                 tag_spec->id = set_tag->id;
    6513                 :          0 :                 tag_mask = tag_spec + 1;
    6514                 :          0 :                 tag_mask->data = UINT32_MAX;
    6515         [ #  # ]:          0 :                 for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    6516         [ #  # ]:          0 :                         if (items->type == RTE_FLOW_ITEM_TYPE_PORT_ID ||
    6517                 :            :                             items->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR ||
    6518                 :            :                             items->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) {
    6519                 :            :                                 memcpy(sfx_items, items, sizeof(*sfx_items));
    6520                 :          0 :                                 sfx_items++;
    6521                 :          0 :                                 break;
    6522                 :            :                         }
    6523                 :            :                 }
    6524                 :          0 :                 sfx_items[0] = (struct rte_flow_item){
    6525                 :            :                         .type = (enum rte_flow_item_type)
    6526                 :            :                                 MLX5_RTE_FLOW_ITEM_TYPE_TAG,
    6527                 :            :                         .spec = tag_spec,
    6528                 :            :                         .last = NULL,
    6529                 :            :                         .mask = tag_mask,
    6530                 :            :                 };
    6531                 :          0 :                 sfx_items[1] = (struct rte_flow_item){
    6532                 :            :                         .type = (enum rte_flow_item_type)
    6533                 :            :                                 RTE_FLOW_ITEM_TYPE_END,
    6534                 :            :                 };
    6535                 :            :                 /* Prepare the tag action in prefix subflow. */
    6536         [ #  # ]:          0 :                 set_tag_idx = (set_tag_idx == -1) ? index : set_tag_idx;
    6537                 :          0 :                 actions_pre[set_tag_idx] =
    6538                 :            :                         (struct rte_flow_action){
    6539                 :            :                         .type = (enum rte_flow_action_type)
    6540                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_TAG,
    6541                 :            :                         .conf = set_tag,
    6542                 :            :                 };
    6543                 :            :                 /* Update next sample position due to add one tag action */
    6544                 :          0 :                 index += 1;
    6545                 :            :         }
    6546                 :            :         /* Copy the sample action into prefix flow. */
    6547         [ #  # ]:          0 :         memcpy(actions_pre + index, actions + sample_action_pos,
    6548                 :            :                sizeof(struct rte_flow_action));
    6549                 :          0 :         index += 1;
    6550                 :            :         /* For the modify action after the sample action in E-Switch mirroring,
    6551                 :            :          * Add the extra jump action in prefix subflow and jump into the next
    6552                 :            :          * table, then do the modify action in the new table.
    6553                 :            :          */
    6554         [ #  # ]:          0 :         if (jump_table) {
    6555                 :            :                 /* Prepare the prefix jump action. */
    6556                 :          0 :                 append_index++;
    6557                 :          0 :                 jump_action = (void *)(actions_pre + actions_n + append_index);
    6558                 :          0 :                 jump_action->group = jump_table;
    6559                 :          0 :                 actions_pre[index++] =
    6560                 :            :                         (struct rte_flow_action){
    6561                 :            :                         .type = (enum rte_flow_action_type)
    6562                 :            :                                 RTE_FLOW_ACTION_TYPE_JUMP,
    6563                 :            :                         .conf = jump_action,
    6564                 :            :                 };
    6565                 :            :         }
    6566                 :          0 :         actions_pre[index] = (struct rte_flow_action){
    6567                 :            :                 .type = (enum rte_flow_action_type)
    6568                 :            :                         RTE_FLOW_ACTION_TYPE_END,
    6569                 :            :         };
    6570                 :            :         /* Put the actions after sample into Suffix flow. */
    6571                 :          0 :         memcpy(actions_sfx, actions + sample_action_pos + 1,
    6572                 :            :                sizeof(struct rte_flow_action) *
    6573                 :          0 :                (actions_n - sample_action_pos - 1));
    6574                 :          0 :         return tag_id;
    6575                 :            : }
    6576                 :            : 
    6577                 :            : /**
    6578                 :            :  * The splitting for metadata feature.
    6579                 :            :  *
    6580                 :            :  * - Q/RSS action on NIC Rx should be split in order to pass by
    6581                 :            :  *   the mreg copy table (RX_CP_TBL) and then it jumps to the
    6582                 :            :  *   action table (RX_ACT_TBL) which has the split Q/RSS action.
    6583                 :            :  *
    6584                 :            :  * - All the actions on NIC Tx should have a mreg copy action to
    6585                 :            :  *   copy reg_a from WQE to reg_c[0].
    6586                 :            :  *
    6587                 :            :  * @param dev
    6588                 :            :  *   Pointer to Ethernet device.
    6589                 :            :  * @param[in] flow
    6590                 :            :  *   Parent flow structure pointer.
    6591                 :            :  * @param[in] attr
    6592                 :            :  *   Flow rule attributes.
    6593                 :            :  * @param[in] items
    6594                 :            :  *   Pattern specification (list terminated by the END pattern item).
    6595                 :            :  * @param[in] actions
    6596                 :            :  *   Associated actions (list terminated by the END action).
    6597                 :            :  * @param[in] flow_split_info
    6598                 :            :  *   Pointer to flow split info structure.
    6599                 :            :  * @param[out] error
    6600                 :            :  *   Perform verbose error reporting if not NULL.
    6601                 :            :  * @return
    6602                 :            :  *   0 on success, negative value otherwise
    6603                 :            :  */
    6604                 :            : static int
    6605                 :          0 : flow_create_split_metadata(struct rte_eth_dev *dev,
    6606                 :            :                            struct rte_flow *flow,
    6607                 :            :                            const struct rte_flow_attr *attr,
    6608                 :            :                            const struct rte_flow_item items[],
    6609                 :            :                            const struct rte_flow_action actions[],
    6610                 :            :                            struct mlx5_flow_split_info *flow_split_info,
    6611                 :            :                            struct rte_flow_error *error)
    6612                 :            : {
    6613                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6614                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    6615                 :          0 :         const struct rte_flow_action *qrss = NULL;
    6616                 :            :         struct rte_flow_action *ext_actions = NULL;
    6617                 :          0 :         struct mlx5_flow *dev_flow = NULL;
    6618                 :            :         uint32_t qrss_id = 0;
    6619                 :            :         int mtr_sfx = 0;
    6620                 :            :         size_t act_size;
    6621                 :            :         int actions_n;
    6622                 :            :         int encap_idx;
    6623                 :            :         int ret;
    6624                 :            : 
    6625                 :            :         /* Check whether extensive metadata feature is engaged. */
    6626         [ #  # ]:          0 :         if (!config->dv_flow_en ||
    6627   [ #  #  #  # ]:          0 :             config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
    6628                 :          0 :             !mlx5_flow_ext_mreg_supported(dev))
    6629                 :          0 :                 return flow_create_split_inner(dev, flow, NULL, attr, items,
    6630                 :            :                                                actions, flow_split_info, error);
    6631                 :          0 :         actions_n = flow_parse_metadata_split_actions_info(actions, &qrss,
    6632                 :            :                                                            &encap_idx);
    6633         [ #  # ]:          0 :         if (qrss) {
    6634                 :            :                 /* Exclude hairpin flows from splitting. */
    6635         [ #  # ]:          0 :                 if (qrss->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
    6636                 :            :                         const struct rte_flow_action_queue *queue;
    6637                 :            : 
    6638                 :          0 :                         queue = qrss->conf;
    6639         [ #  # ]:          0 :                         if (mlx5_rxq_is_hairpin(dev, queue->index))
    6640                 :          0 :                                 qrss = NULL;
    6641         [ #  # ]:          0 :                 } else if (qrss->type == RTE_FLOW_ACTION_TYPE_RSS) {
    6642                 :            :                         const struct rte_flow_action_rss *rss;
    6643                 :            : 
    6644                 :          0 :                         rss = qrss->conf;
    6645         [ #  # ]:          0 :                         if (mlx5_rxq_is_hairpin(dev, rss->queue[0]))
    6646                 :          0 :                                 qrss = NULL;
    6647                 :            :                 }
    6648                 :            :         }
    6649         [ #  # ]:          0 :         if (qrss) {
    6650                 :            :                 /* Check if it is in meter suffix table. */
    6651                 :          0 :                 mtr_sfx = attr->group ==
    6652         [ #  # ]:          0 :                           ((attr->transfer && priv->fdb_def_rule) ?
    6653         [ #  # ]:          0 :                           (MLX5_FLOW_TABLE_LEVEL_METER - 1) :
    6654                 :            :                           MLX5_FLOW_TABLE_LEVEL_METER);
    6655                 :            :                 /*
    6656                 :            :                  * Q/RSS action on NIC Rx should be split in order to pass by
    6657                 :            :                  * the mreg copy table (RX_CP_TBL) and then it jumps to the
    6658                 :            :                  * action table (RX_ACT_TBL) which has the split Q/RSS action.
    6659                 :            :                  */
    6660                 :          0 :                 act_size = sizeof(struct rte_flow_action) * (actions_n + 1) +
    6661                 :          0 :                            sizeof(struct rte_flow_action_set_tag) +
    6662                 :            :                            sizeof(struct rte_flow_action_jump);
    6663                 :          0 :                 ext_actions = mlx5_malloc(MLX5_MEM_ZERO, act_size, 0,
    6664                 :            :                                           SOCKET_ID_ANY);
    6665         [ #  # ]:          0 :                 if (!ext_actions)
    6666                 :          0 :                         return rte_flow_error_set(error, ENOMEM,
    6667                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6668                 :            :                                                   NULL, "no memory to split "
    6669                 :            :                                                   "metadata flow");
    6670                 :            :                 /*
    6671                 :            :                  * Create the new actions list with removed Q/RSS action
    6672                 :            :                  * and appended set tag and jump to register copy table
    6673                 :            :                  * (RX_CP_TBL). We should preallocate unique tag ID here
    6674                 :            :                  * in advance, because it is needed for set tag action.
    6675                 :            :                  */
    6676                 :          0 :                 qrss_id = flow_mreg_split_qrss_prep(dev, ext_actions, actions,
    6677                 :            :                                                     qrss, actions_n,
    6678                 :            :                                                     mtr_sfx, error);
    6679         [ #  # ]:          0 :                 if (!mtr_sfx && !qrss_id) {
    6680                 :          0 :                         ret = -rte_errno;
    6681                 :          0 :                         goto exit;
    6682                 :            :                 }
    6683         [ #  # ]:          0 :         } else if (attr->egress) {
    6684                 :            :                 /*
    6685                 :            :                  * All the actions on NIC Tx should have a metadata register
    6686                 :            :                  * copy action to copy reg_a from WQE to reg_c[meta]
    6687                 :            :                  */
    6688                 :          0 :                 act_size = sizeof(struct rte_flow_action) * (actions_n + 1) +
    6689                 :            :                            sizeof(struct mlx5_flow_action_copy_mreg);
    6690                 :          0 :                 ext_actions = mlx5_malloc(MLX5_MEM_ZERO, act_size, 0,
    6691                 :            :                                           SOCKET_ID_ANY);
    6692         [ #  # ]:          0 :                 if (!ext_actions)
    6693                 :          0 :                         return rte_flow_error_set(error, ENOMEM,
    6694                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6695                 :            :                                                   NULL, "no memory to split "
    6696                 :            :                                                   "metadata flow");
    6697                 :            :                 /* Create the action list appended with copy register. */
    6698                 :          0 :                 ret = flow_mreg_tx_copy_prep(dev, ext_actions, actions,
    6699                 :            :                                              actions_n, error, encap_idx);
    6700         [ #  # ]:          0 :                 if (ret < 0)
    6701                 :          0 :                         goto exit;
    6702                 :            :         }
    6703                 :            :         /* Add the unmodified original or prefix subflow. */
    6704         [ #  # ]:          0 :         ret = flow_create_split_inner(dev, flow, &dev_flow, attr,
    6705                 :            :                                       items, ext_actions ? ext_actions :
    6706                 :            :                                       actions, flow_split_info, error);
    6707         [ #  # ]:          0 :         if (ret < 0)
    6708                 :          0 :                 goto exit;
    6709                 :            :         MLX5_ASSERT(dev_flow);
    6710         [ #  # ]:          0 :         if (qrss) {
    6711                 :          0 :                 const struct rte_flow_attr q_attr = {
    6712                 :            :                         .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP,
    6713                 :            :                         .ingress = 1,
    6714                 :            :                 };
    6715                 :            :                 /* Internal PMD action to set register. */
    6716                 :          0 :                 struct mlx5_rte_flow_item_tag q_tag_spec = {
    6717                 :            :                         .data = qrss_id,
    6718                 :            :                         .id = REG_NON,
    6719                 :            :                 };
    6720                 :          0 :                 struct rte_flow_item q_items[] = {
    6721                 :            :                         {
    6722                 :            :                                 .type = (enum rte_flow_item_type)
    6723                 :            :                                         MLX5_RTE_FLOW_ITEM_TYPE_TAG,
    6724                 :            :                                 .spec = &q_tag_spec,
    6725                 :            :                                 .last = NULL,
    6726                 :            :                                 .mask = NULL,
    6727                 :            :                         },
    6728                 :            :                         {
    6729                 :            :                                 .type = RTE_FLOW_ITEM_TYPE_END,
    6730                 :            :                         },
    6731                 :            :                 };
    6732                 :          0 :                 struct rte_flow_action q_actions[] = {
    6733                 :            :                         {
    6734                 :          0 :                                 .type = qrss->type,
    6735                 :          0 :                                 .conf = qrss->conf,
    6736                 :            :                         },
    6737                 :            :                         {
    6738                 :            :                                 .type = RTE_FLOW_ACTION_TYPE_END,
    6739                 :            :                         },
    6740                 :            :                 };
    6741                 :          0 :                 uint64_t layers = flow_get_prefix_layer_flags(dev_flow);
    6742                 :            : 
    6743                 :            :                 /*
    6744                 :            :                  * Configure the tag item only if there is no meter subflow.
    6745                 :            :                  * Since tag is already marked in the meter suffix subflow
    6746                 :            :                  * we can just use the meter suffix items as is.
    6747                 :            :                  */
    6748         [ #  # ]:          0 :                 if (qrss_id) {
    6749                 :            :                         /* Not meter subflow. */
    6750                 :            :                         MLX5_ASSERT(!mtr_sfx);
    6751                 :            :                         /*
    6752                 :            :                          * Put unique id in prefix flow due to it is destroyed
    6753                 :            :                          * after suffix flow and id will be freed after there
    6754                 :            :                          * is no actual flows with this id and identifier
    6755                 :            :                          * reallocation becomes possible (for example, for
    6756                 :            :                          * other flows in other threads).
    6757                 :            :                          */
    6758                 :          0 :                         dev_flow->handle->split_flow_id = qrss_id;
    6759                 :          0 :                         ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0,
    6760                 :            :                                                    error);
    6761         [ #  # ]:          0 :                         if (ret < 0)
    6762                 :          0 :                                 goto exit;
    6763                 :          0 :                         q_tag_spec.id = ret;
    6764                 :            :                 }
    6765                 :          0 :                 dev_flow = NULL;
    6766                 :            :                 /* Add suffix subflow to execute Q/RSS. */
    6767                 :          0 :                 flow_split_info->prefix_layers = layers;
    6768                 :          0 :                 flow_split_info->prefix_mark = 0;
    6769                 :          0 :                 flow_split_info->table_id = 0;
    6770         [ #  # ]:          0 :                 ret = flow_create_split_inner(dev, flow, &dev_flow,
    6771                 :            :                                               &q_attr, mtr_sfx ? items :
    6772                 :            :                                               q_items, q_actions,
    6773                 :            :                                               flow_split_info, error);
    6774         [ #  # ]:          0 :                 if (ret < 0)
    6775                 :          0 :                         goto exit;
    6776                 :            :                 /* qrss ID should be freed if failed. */
    6777                 :            :                 qrss_id = 0;
    6778                 :            :                 MLX5_ASSERT(dev_flow);
    6779                 :            :         }
    6780                 :            : 
    6781                 :          0 : exit:
    6782                 :            :         /*
    6783                 :            :          * We do not destroy the partially created sub_flows in case of error.
    6784                 :            :          * These ones are included into parent flow list and will be destroyed
    6785                 :            :          * by flow_drv_destroy.
    6786                 :            :          */
    6787                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_EXPANTION_FLOW_ID],
    6788                 :            :                         qrss_id);
    6789                 :          0 :         mlx5_free(ext_actions);
    6790                 :          0 :         return ret;
    6791                 :            : }
    6792                 :            : 
    6793                 :            : /**
    6794                 :            :  * Create meter internal drop flow with the original pattern.
    6795                 :            :  *
    6796                 :            :  * @param dev
    6797                 :            :  *   Pointer to Ethernet device.
    6798                 :            :  * @param[in] flow
    6799                 :            :  *   Parent flow structure pointer.
    6800                 :            :  * @param[in] attr
    6801                 :            :  *   Flow rule attributes.
    6802                 :            :  * @param[in] items
    6803                 :            :  *   Pattern specification (list terminated by the END pattern item).
    6804                 :            :  * @param[in] flow_split_info
    6805                 :            :  *   Pointer to flow split info structure.
    6806                 :            :  * @param[in] fm
    6807                 :            :  *   Pointer to flow meter structure.
    6808                 :            :  * @param[out] error
    6809                 :            :  *   Perform verbose error reporting if not NULL.
    6810                 :            :  * @return
    6811                 :            :  *   0 on success, negative value otherwise
    6812                 :            :  */
    6813                 :            : static uint32_t
    6814                 :          0 : flow_meter_create_drop_flow_with_org_pattern(struct rte_eth_dev *dev,
    6815                 :            :                         struct rte_flow *flow,
    6816                 :            :                         const struct rte_flow_attr *attr,
    6817                 :            :                         const struct rte_flow_item items[],
    6818                 :            :                         struct mlx5_flow_split_info *flow_split_info,
    6819                 :            :                         struct mlx5_flow_meter_info *fm,
    6820                 :            :                         struct rte_flow_error *error)
    6821                 :            : {
    6822                 :          0 :         struct mlx5_flow *dev_flow = NULL;
    6823                 :          0 :         struct rte_flow_attr drop_attr = *attr;
    6824                 :            :         struct rte_flow_action drop_actions[3];
    6825                 :          0 :         struct mlx5_flow_split_info drop_split_info = *flow_split_info;
    6826                 :            : 
    6827                 :            :         MLX5_ASSERT(fm->drop_cnt);
    6828                 :          0 :         drop_actions[0].type =
    6829                 :            :                 (enum rte_flow_action_type)MLX5_RTE_FLOW_ACTION_TYPE_COUNT;
    6830                 :          0 :         drop_actions[0].conf = (void *)(uintptr_t)fm->drop_cnt;
    6831                 :          0 :         drop_actions[1].type = RTE_FLOW_ACTION_TYPE_DROP;
    6832                 :          0 :         drop_actions[1].conf = NULL;
    6833                 :          0 :         drop_actions[2].type = RTE_FLOW_ACTION_TYPE_END;
    6834                 :          0 :         drop_actions[2].conf = NULL;
    6835                 :          0 :         drop_split_info.external = false;
    6836                 :          0 :         drop_split_info.skip_scale |= 1 << MLX5_SCALE_FLOW_GROUP_BIT;
    6837                 :          0 :         drop_split_info.table_id = MLX5_MTR_TABLE_ID_DROP;
    6838                 :          0 :         drop_attr.group = MLX5_FLOW_TABLE_LEVEL_METER;
    6839                 :          0 :         return flow_create_split_inner(dev, flow, &dev_flow,
    6840                 :            :                                 &drop_attr, items, drop_actions,
    6841                 :            :                                 &drop_split_info, error);
    6842                 :            : }
    6843                 :            : 
    6844                 :            : static int
    6845                 :            : flow_count_vlan_items(const struct rte_flow_item items[])
    6846                 :            : {
    6847                 :            :         int items_n = 0;
    6848                 :            : 
    6849         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    6850         [ #  # ]:          0 :                 if (items->type == RTE_FLOW_ITEM_TYPE_VLAN ||
    6851                 :            :                     items->type == (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
    6852                 :          0 :                         items_n++;
    6853                 :            :         }
    6854                 :            :         return items_n;
    6855                 :            : }
    6856                 :            : 
    6857                 :            : /**
    6858                 :            :  * The splitting for meter feature.
    6859                 :            :  *
    6860                 :            :  * - The meter flow will be split to two flows as prefix and
    6861                 :            :  *   suffix flow. The packets make sense only it pass the prefix
    6862                 :            :  *   meter action.
    6863                 :            :  *
    6864                 :            :  * - Reg_C_5 is used for the packet to match betweend prefix and
    6865                 :            :  *   suffix flow.
    6866                 :            :  *
    6867                 :            :  * @param dev
    6868                 :            :  *   Pointer to Ethernet device.
    6869                 :            :  * @param[in] flow
    6870                 :            :  *   Parent flow structure pointer.
    6871                 :            :  * @param[in] attr
    6872                 :            :  *   Flow rule attributes.
    6873                 :            :  * @param[in] items
    6874                 :            :  *   Pattern specification (list terminated by the END pattern item).
    6875                 :            :  * @param[in] actions
    6876                 :            :  *   Associated actions (list terminated by the END action).
    6877                 :            :  * @param[in] flow_split_info
    6878                 :            :  *   Pointer to flow split info structure.
    6879                 :            :  * @param[out] error
    6880                 :            :  *   Perform verbose error reporting if not NULL.
    6881                 :            :  * @return
    6882                 :            :  *   0 on success, negative value otherwise
    6883                 :            :  */
    6884                 :            : static int
    6885                 :          0 : flow_create_split_meter(struct rte_eth_dev *dev,
    6886                 :            :                         struct rte_flow *flow,
    6887                 :            :                         const struct rte_flow_attr *attr,
    6888                 :            :                         const struct rte_flow_item items[],
    6889                 :            :                         const struct rte_flow_action actions[],
    6890                 :            :                         struct mlx5_flow_split_info *flow_split_info,
    6891                 :            :                         struct rte_flow_error *error)
    6892                 :            : {
    6893                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6894                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
    6895                 :            :         struct rte_flow_action *sfx_actions = NULL;
    6896                 :            :         struct rte_flow_action *pre_actions = NULL;
    6897                 :            :         struct rte_flow_item *sfx_items = NULL;
    6898                 :          0 :         struct mlx5_flow *dev_flow = NULL;
    6899                 :          0 :         struct rte_flow_attr sfx_attr = *attr;
    6900                 :            :         struct mlx5_flow_meter_info *fm = NULL;
    6901                 :            :         uint8_t skip_scale_restore;
    6902                 :          0 :         bool has_mtr = false;
    6903                 :          0 :         bool has_modify = false;
    6904                 :            :         bool set_mtr_reg = true;
    6905                 :            :         bool is_mtr_hierarchy = false;
    6906                 :          0 :         uint32_t meter_id = 0;
    6907                 :          0 :         uint32_t mtr_idx = 0;
    6908                 :          0 :         uint32_t mtr_flow_id = 0;
    6909                 :            :         size_t act_size;
    6910                 :            :         size_t item_size;
    6911                 :            :         int actions_n = 0;
    6912                 :            :         int vlan_items_n = 0;
    6913                 :            :         int ret = 0;
    6914                 :            : 
    6915         [ #  # ]:          0 :         if (priv->mtr_en)
    6916                 :          0 :                 actions_n = flow_check_meter_action(dev, actions, &has_mtr,
    6917                 :            :                                                     &has_modify, &meter_id);
    6918         [ #  # ]:          0 :         if (has_mtr) {
    6919         [ #  # ]:          0 :                 if (flow->meter) {
    6920                 :          0 :                         fm = flow_dv_meter_find_by_idx(priv, flow->meter);
    6921         [ #  # ]:          0 :                         if (!fm)
    6922                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6923                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6924                 :            :                                                 NULL, "Meter not found.");
    6925                 :            :                 } else {
    6926                 :          0 :                         fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);
    6927         [ #  # ]:          0 :                         if (!fm)
    6928                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6929                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6930                 :            :                                                 NULL, "Meter not found.");
    6931                 :          0 :                         ret = mlx5_flow_meter_attach(priv, fm,
    6932                 :            :                                                      &sfx_attr, error);
    6933         [ #  # ]:          0 :                         if (ret)
    6934                 :          0 :                                 return -rte_errno;
    6935                 :          0 :                         flow->meter = mtr_idx;
    6936                 :            :                 }
    6937                 :            :                 MLX5_ASSERT(wks);
    6938                 :          0 :                 wks->fm = fm;
    6939         [ #  # ]:          0 :                 if (!fm->def_policy) {
    6940                 :          0 :                         wks->policy = mlx5_flow_meter_policy_find(dev,
    6941                 :            :                                                                   fm->policy_id,
    6942                 :            :                                                                   NULL);
    6943                 :            :                         MLX5_ASSERT(wks->policy);
    6944         [ #  # ]:          0 :                         if (wks->policy->mark)
    6945                 :          0 :                                 wks->mark = 1;
    6946         [ #  # ]:          0 :                         if (wks->policy->is_hierarchy) {
    6947                 :          0 :                                 wks->final_policy =
    6948                 :          0 :                                 mlx5_flow_meter_hierarchy_get_final_policy(dev,
    6949                 :            :                                                                 wks->policy);
    6950         [ #  # ]:          0 :                                 if (!wks->final_policy)
    6951                 :          0 :                                         return rte_flow_error_set(error,
    6952                 :            :                                         EINVAL,
    6953                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6954                 :            :                                 "Failed to find terminal policy of hierarchy.");
    6955                 :            :                                 is_mtr_hierarchy = true;
    6956                 :            :                         }
    6957                 :            :                 }
    6958                 :            :                 /*
    6959                 :            :                  * If it isn't default-policy Meter, and
    6960                 :            :                  * 1. Not meter hierarchy and there's no action in flow to change
    6961                 :            :                  *    packet (modify/encap/decap etc.), OR
    6962                 :            :                  * 2. No drop count needed for this meter.
    6963                 :            :                  * Then no need to use regC to save meter id anymore.
    6964                 :            :                  */
    6965   [ #  #  #  #  :          0 :                 if (!fm->def_policy && ((!has_modify && !is_mtr_hierarchy) || !fm->drop_cnt))
             #  #  #  # ]
    6966                 :            :                         set_mtr_reg = false;
    6967                 :            :                 /* Prefix actions: meter, decap, encap, tag, jump, end, cnt. */
    6968                 :            : #define METER_PREFIX_ACTION 7
    6969                 :          0 :                 act_size = (sizeof(struct rte_flow_action) *
    6970                 :          0 :                             (actions_n + METER_PREFIX_ACTION)) +
    6971                 :            :                            sizeof(struct mlx5_rte_flow_action_set_tag);
    6972                 :            :                 /* Flow can have multiple VLAN items. Account for them in suffix items. */
    6973                 :            :                 vlan_items_n = flow_count_vlan_items(items);
    6974                 :            :                 /* Suffix items: tag, [vlans], port id, end. */
    6975                 :            : #define METER_SUFFIX_ITEM 3
    6976                 :          0 :                 item_size = sizeof(struct rte_flow_item) * (METER_SUFFIX_ITEM + vlan_items_n) +
    6977                 :            :                             sizeof(struct mlx5_rte_flow_item_tag) * 2;
    6978                 :          0 :                 sfx_actions = mlx5_malloc(MLX5_MEM_ZERO, (act_size + item_size),
    6979                 :            :                                           0, SOCKET_ID_ANY);
    6980         [ #  # ]:          0 :                 if (!sfx_actions)
    6981                 :          0 :                         return rte_flow_error_set(error, ENOMEM,
    6982                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6983                 :            :                                                   NULL, "no memory to split "
    6984                 :            :                                                   "meter flow");
    6985                 :          0 :                 sfx_items = (struct rte_flow_item *)((char *)sfx_actions +
    6986                 :            :                              act_size);
    6987                 :            :                 /* There's no suffix flow for meter of non-default policy. */
    6988         [ #  # ]:          0 :                 if (!fm->def_policy)
    6989                 :          0 :                         pre_actions = sfx_actions + 1;
    6990                 :            :                 else
    6991                 :          0 :                         pre_actions = sfx_actions + actions_n;
    6992         [ #  # ]:          0 :                 ret = flow_meter_split_prep(dev, flow, wks, &sfx_attr,
    6993                 :            :                                             items, sfx_items, actions,
    6994                 :            :                                             sfx_actions, pre_actions,
    6995                 :            :                                             (set_mtr_reg ? &mtr_flow_id : NULL),
    6996                 :            :                                             error);
    6997         [ #  # ]:          0 :                 if (ret) {
    6998                 :          0 :                         ret = -rte_errno;
    6999                 :          0 :                         goto exit;
    7000                 :            :                 }
    7001                 :            :                 /* Add the prefix subflow. */
    7002                 :          0 :                 skip_scale_restore = flow_split_info->skip_scale;
    7003                 :          0 :                 flow_split_info->skip_scale |=
    7004                 :            :                         1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT;
    7005                 :          0 :                 ret = flow_create_split_inner(dev, flow, &dev_flow,
    7006                 :            :                                               attr, items, pre_actions,
    7007                 :            :                                               flow_split_info, error);
    7008                 :          0 :                 flow_split_info->skip_scale = skip_scale_restore;
    7009         [ #  # ]:          0 :                 if (ret) {
    7010         [ #  # ]:          0 :                         if (mtr_flow_id)
    7011                 :          0 :                                 mlx5_ipool_free(fm->flow_ipool, mtr_flow_id);
    7012                 :          0 :                         ret = -rte_errno;
    7013                 :          0 :                         goto exit;
    7014                 :            :                 }
    7015         [ #  # ]:          0 :                 if (mtr_flow_id) {
    7016                 :          0 :                         dev_flow->handle->split_flow_id = mtr_flow_id;
    7017                 :          0 :                         dev_flow->handle->is_meter_flow_id = 1;
    7018                 :            :                 }
    7019         [ #  # ]:          0 :                 if (!fm->def_policy) {
    7020   [ #  #  #  # ]:          0 :                         if (!set_mtr_reg && fm->drop_cnt)
    7021                 :          0 :                                 ret =
    7022                 :          0 :                         flow_meter_create_drop_flow_with_org_pattern(dev, flow,
    7023                 :            :                                                         &sfx_attr, items,
    7024                 :            :                                                         flow_split_info,
    7025                 :            :                                                         fm, error);
    7026                 :          0 :                         goto exit;
    7027                 :            :                 }
    7028                 :            :                 /* Setting the sfx group atrr. */
    7029                 :          0 :                 sfx_attr.group = sfx_attr.transfer ?
    7030         [ #  # ]:          0 :                                 (MLX5_FLOW_TABLE_LEVEL_METER - 1) :
    7031                 :            :                                  MLX5_FLOW_TABLE_LEVEL_METER;
    7032                 :          0 :                 flow_split_info->prefix_layers =
    7033                 :          0 :                                 flow_get_prefix_layer_flags(dev_flow);
    7034                 :          0 :                 flow_split_info->prefix_mark |= wks->mark;
    7035                 :          0 :                 flow_split_info->table_id = MLX5_MTR_TABLE_ID_SUFFIX;
    7036                 :            :         }
    7037                 :            :         /* Add the prefix subflow. */
    7038         [ #  # ]:          0 :         ret = flow_create_split_metadata(dev, flow,
    7039                 :            :                                          &sfx_attr, sfx_items ?
    7040                 :            :                                          sfx_items : items,
    7041                 :            :                                          sfx_actions ? sfx_actions : actions,
    7042                 :            :                                          flow_split_info, error);
    7043                 :          0 : exit:
    7044         [ #  # ]:          0 :         if (sfx_actions)
    7045                 :          0 :                 mlx5_free(sfx_actions);
    7046                 :            :         return ret;
    7047                 :            : }
    7048                 :            : 
    7049                 :            : /**
    7050                 :            :  * The splitting for sample feature.
    7051                 :            :  *
    7052                 :            :  * Once Sample action is detected in the action list, the flow actions should
    7053                 :            :  * be split into prefix sub flow and suffix sub flow.
    7054                 :            :  *
    7055                 :            :  * The original items remain in the prefix sub flow, all actions preceding the
    7056                 :            :  * sample action and the sample action itself will be copied to the prefix
    7057                 :            :  * sub flow, the actions following the sample action will be copied to the
    7058                 :            :  * suffix sub flow, Queue action always be located in the suffix sub flow.
    7059                 :            :  *
    7060                 :            :  * In order to make the packet from prefix sub flow matches with suffix sub
    7061                 :            :  * flow, an extra tag action be added into prefix sub flow, and the suffix sub
    7062                 :            :  * flow uses tag item with the unique flow id.
    7063                 :            :  *
    7064                 :            :  * @param dev
    7065                 :            :  *   Pointer to Ethernet device.
    7066                 :            :  * @param[in] flow
    7067                 :            :  *   Parent flow structure pointer.
    7068                 :            :  * @param[in] attr
    7069                 :            :  *   Flow rule attributes.
    7070                 :            :  * @param[in] items
    7071                 :            :  *   Pattern specification (list terminated by the END pattern item).
    7072                 :            :  * @param[in] actions
    7073                 :            :  *   Associated actions (list terminated by the END action).
    7074                 :            :  * @param[in] flow_split_info
    7075                 :            :  *   Pointer to flow split info structure.
    7076                 :            :  * @param[out] error
    7077                 :            :  *   Perform verbose error reporting if not NULL.
    7078                 :            :  * @return
    7079                 :            :  *   0 on success, negative value otherwise
    7080                 :            :  */
    7081                 :            : static int
    7082                 :          0 : flow_create_split_sample(struct rte_eth_dev *dev,
    7083                 :            :                          struct rte_flow *flow,
    7084                 :            :                          const struct rte_flow_attr *attr,
    7085                 :            :                          const struct rte_flow_item items[],
    7086                 :            :                          const struct rte_flow_action actions[],
    7087                 :            :                          struct mlx5_flow_split_info *flow_split_info,
    7088                 :            :                          struct rte_flow_error *error)
    7089                 :            : {
    7090                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7091                 :            :         struct rte_flow_action *sfx_actions = NULL;
    7092                 :            :         struct rte_flow_action *pre_actions = NULL;
    7093                 :            :         struct rte_flow_item *sfx_items = NULL;
    7094                 :          0 :         struct mlx5_flow *dev_flow = NULL;
    7095                 :          0 :         struct rte_flow_attr sfx_attr = *attr;
    7096                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
    7097                 :            :         struct mlx5_flow_dv_sample_resource *sample_res;
    7098                 :            :         struct mlx5_flow_tbl_data_entry *sfx_tbl_data;
    7099                 :            :         struct mlx5_flow_tbl_resource *sfx_tbl;
    7100                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
    7101                 :            : #endif
    7102                 :            :         size_t act_size;
    7103                 :            :         size_t item_size;
    7104                 :            :         uint32_t fdb_tx = 0;
    7105                 :            :         int32_t tag_id = 0;
    7106                 :            :         int actions_n = 0;
    7107                 :            :         int sample_action_pos;
    7108                 :            :         int qrss_action_pos;
    7109                 :            :         int add_tag = 0;
    7110                 :          0 :         int modify_after_mirror = 0;
    7111                 :            :         uint16_t jump_table = 0;
    7112                 :            :         const uint32_t next_ft_step = 1;
    7113                 :            :         int ret = 0;
    7114                 :            :         struct mlx5_priv *item_port_priv = NULL;
    7115                 :            :         const struct rte_flow_item *item;
    7116                 :            : 
    7117         [ #  # ]:          0 :         if (priv->sampler_en)
    7118                 :          0 :                 actions_n = flow_check_match_action(actions, attr,
    7119                 :            :                                         RTE_FLOW_ACTION_TYPE_SAMPLE,
    7120                 :            :                                         &sample_action_pos, &qrss_action_pos,
    7121                 :            :                                         &modify_after_mirror);
    7122         [ #  # ]:          0 :         if (actions_n) {
    7123                 :            :                 /* The prefix actions must includes sample, tag, end. */
    7124                 :          0 :                 act_size = sizeof(struct rte_flow_action) * (actions_n * 2 + 1)
    7125                 :            :                            + sizeof(struct mlx5_rte_flow_action_set_tag);
    7126                 :            :                 item_size = sizeof(struct rte_flow_item) * SAMPLE_SUFFIX_ITEM +
    7127                 :            :                             sizeof(struct mlx5_rte_flow_item_tag) * 2;
    7128                 :          0 :                 sfx_actions = mlx5_malloc(MLX5_MEM_ZERO, (act_size +
    7129                 :            :                                           item_size), 0, SOCKET_ID_ANY);
    7130         [ #  # ]:          0 :                 if (!sfx_actions)
    7131                 :          0 :                         return rte_flow_error_set(error, ENOMEM,
    7132                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    7133                 :            :                                                   NULL, "no memory to split "
    7134                 :            :                                                   "sample flow");
    7135         [ #  # ]:          0 :                 for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
    7136         [ #  # ]:          0 :                         if (item->type == RTE_FLOW_ITEM_TYPE_PORT_ID) {
    7137                 :            :                                 const struct rte_flow_item_port_id *spec;
    7138                 :            : 
    7139                 :          0 :                                 spec = (const struct rte_flow_item_port_id *)item->spec;
    7140         [ #  # ]:          0 :                                 if (spec)
    7141                 :            :                                         item_port_priv =
    7142                 :          0 :                                                 mlx5_port_to_eswitch_info(spec->id, true);
    7143                 :            :                                 break;
    7144         [ #  # ]:          0 :                         } else if (item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) {
    7145                 :            :                                 const struct rte_flow_item_ethdev *spec;
    7146                 :            : 
    7147                 :          0 :                                 spec = (const struct rte_flow_item_ethdev *)item->spec;
    7148         [ #  # ]:          0 :                                 if (spec)
    7149                 :            :                                         item_port_priv =
    7150                 :          0 :                                                 mlx5_port_to_eswitch_info(spec->port_id, true);
    7151                 :            :                                 break;
    7152         [ #  # ]:          0 :                         } else if (item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
    7153                 :            :                                 const struct rte_flow_item_ethdev *spec;
    7154                 :            : 
    7155                 :          0 :                                 spec = (const struct rte_flow_item_ethdev *)item->spec;
    7156         [ #  # ]:          0 :                                 if (spec)
    7157                 :            :                                         item_port_priv =
    7158                 :          0 :                                                 mlx5_port_to_eswitch_info(spec->port_id, true);
    7159                 :            :                                 break;
    7160                 :            :                         }
    7161                 :            :                 }
    7162                 :            :                 /* The representor_id is UINT16_MAX for uplink. */
    7163   [ #  #  #  # ]:          0 :                 fdb_tx = (attr->transfer &&
    7164                 :            :                           flow_source_vport_representor(priv, item_port_priv));
    7165                 :            :                 /*
    7166                 :            :                  * When reg_c_preserve is set, metadata registers Cx preserve
    7167                 :            :                  * their value even through packet duplication.
    7168                 :            :                  */
    7169                 :          0 :                 add_tag = (!fdb_tx ||
    7170         [ #  # ]:          0 :                            priv->sh->cdev->config.hca_attr.reg_c_preserve);
    7171                 :            :                 if (add_tag)
    7172                 :          0 :                         sfx_items = (struct rte_flow_item *)((char *)sfx_actions
    7173                 :            :                                         + act_size);
    7174         [ #  # ]:          0 :                 if (modify_after_mirror)
    7175                 :          0 :                         jump_table = attr->group * MLX5_FLOW_TABLE_FACTOR +
    7176                 :            :                                      next_ft_step;
    7177                 :          0 :                 pre_actions = sfx_actions + actions_n;
    7178                 :          0 :                 tag_id = flow_sample_split_prep(dev, add_tag, items, sfx_items,
    7179                 :            :                                                 actions, sfx_actions,
    7180                 :            :                                                 pre_actions, actions_n,
    7181                 :            :                                                 sample_action_pos,
    7182                 :            :                                                 qrss_action_pos, jump_table,
    7183                 :            :                                                 error);
    7184   [ #  #  #  # ]:          0 :                 if (tag_id < 0 || (add_tag && !tag_id)) {
    7185                 :          0 :                         ret = -rte_errno;
    7186                 :          0 :                         goto exit;
    7187                 :            :                 }
    7188         [ #  # ]:          0 :                 if (modify_after_mirror)
    7189                 :          0 :                         flow_split_info->skip_scale =
    7190                 :            :                                         1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT;
    7191                 :            :                 /* Add the prefix subflow. */
    7192                 :          0 :                 ret = flow_create_split_inner(dev, flow, &dev_flow, attr,
    7193                 :            :                                               items, pre_actions,
    7194                 :            :                                               flow_split_info, error);
    7195         [ #  # ]:          0 :                 if (ret) {
    7196                 :          0 :                         ret = -rte_errno;
    7197                 :          0 :                         goto exit;
    7198                 :            :                 }
    7199                 :          0 :                 dev_flow->handle->split_flow_id = tag_id;
    7200                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
    7201         [ #  # ]:          0 :                 if (!modify_after_mirror) {
    7202                 :            :                         /* Set the sfx group attr. */
    7203                 :          0 :                         sample_res = (struct mlx5_flow_dv_sample_resource *)
    7204                 :            :                                                 dev_flow->dv.sample_res;
    7205                 :          0 :                         sfx_tbl = (struct mlx5_flow_tbl_resource *)
    7206                 :            :                                                 sample_res->normal_path_tbl;
    7207                 :          0 :                         sfx_tbl_data = container_of(sfx_tbl,
    7208                 :            :                                                 struct mlx5_flow_tbl_data_entry,
    7209                 :            :                                                 tbl);
    7210                 :          0 :                         sfx_attr.group = sfx_attr.transfer ?
    7211         [ #  # ]:          0 :                         (sfx_tbl_data->level - 1) : sfx_tbl_data->level;
    7212                 :            :                 } else {
    7213                 :            :                         MLX5_ASSERT(attr->transfer);
    7214                 :          0 :                         sfx_attr.group = jump_table;
    7215                 :            :                 }
    7216                 :          0 :                 flow_split_info->prefix_layers =
    7217                 :          0 :                                 flow_get_prefix_layer_flags(dev_flow);
    7218                 :            :                 MLX5_ASSERT(wks);
    7219                 :          0 :                 flow_split_info->prefix_mark |= wks->mark;
    7220                 :            :                 /* Suffix group level already be scaled with factor, set
    7221                 :            :                  * MLX5_SCALE_FLOW_GROUP_BIT of skip_scale to 1 to avoid scale
    7222                 :            :                  * again in translation.
    7223                 :            :                  */
    7224                 :          0 :                 flow_split_info->skip_scale = 1 << MLX5_SCALE_FLOW_GROUP_BIT;
    7225                 :            : #endif
    7226                 :            :         }
    7227                 :            :         /* Add the suffix subflow. */
    7228   [ #  #  #  # ]:          0 :         ret = flow_create_split_meter(dev, flow, &sfx_attr,
    7229                 :            :                                       sfx_items ? sfx_items : items,
    7230                 :            :                                       sfx_actions ? sfx_actions : actions,
    7231                 :            :                                       flow_split_info, error);
    7232                 :          0 : exit:
    7233         [ #  # ]:          0 :         if (sfx_actions)
    7234                 :          0 :                 mlx5_free(sfx_actions);
    7235                 :            :         return ret;
    7236                 :            : }
    7237                 :            : 
    7238                 :            : /**
    7239                 :            :  * Split the flow to subflow set. The splitters might be linked
    7240                 :            :  * in the chain, like this:
    7241                 :            :  * flow_create_split_outer() calls:
    7242                 :            :  *   flow_create_split_meter() calls:
    7243                 :            :  *     flow_create_split_metadata(meter_subflow_0) calls:
    7244                 :            :  *       flow_create_split_inner(metadata_subflow_0)
    7245                 :            :  *       flow_create_split_inner(metadata_subflow_1)
    7246                 :            :  *       flow_create_split_inner(metadata_subflow_2)
    7247                 :            :  *     flow_create_split_metadata(meter_subflow_1) calls:
    7248                 :            :  *       flow_create_split_inner(metadata_subflow_0)
    7249                 :            :  *       flow_create_split_inner(metadata_subflow_1)
    7250                 :            :  *       flow_create_split_inner(metadata_subflow_2)
    7251                 :            :  *
    7252                 :            :  * This provide flexible way to add new levels of flow splitting.
    7253                 :            :  * The all of successfully created subflows are included to the
    7254                 :            :  * parent flow dev_flow list.
    7255                 :            :  *
    7256                 :            :  * @param dev
    7257                 :            :  *   Pointer to Ethernet device.
    7258                 :            :  * @param[in] flow
    7259                 :            :  *   Parent flow structure pointer.
    7260                 :            :  * @param[in] attr
    7261                 :            :  *   Flow rule attributes.
    7262                 :            :  * @param[in] items
    7263                 :            :  *   Pattern specification (list terminated by the END pattern item).
    7264                 :            :  * @param[in] actions
    7265                 :            :  *   Associated actions (list terminated by the END action).
    7266                 :            :  * @param[in] flow_split_info
    7267                 :            :  *   Pointer to flow split info structure.
    7268                 :            :  * @param[out] error
    7269                 :            :  *   Perform verbose error reporting if not NULL.
    7270                 :            :  * @return
    7271                 :            :  *   0 on success, negative value otherwise
    7272                 :            :  */
    7273                 :            : static int
    7274                 :            : flow_create_split_outer(struct rte_eth_dev *dev,
    7275                 :            :                         struct rte_flow *flow,
    7276                 :            :                         const struct rte_flow_attr *attr,
    7277                 :            :                         const struct rte_flow_item items[],
    7278                 :            :                         const struct rte_flow_action actions[],
    7279                 :            :                         struct mlx5_flow_split_info *flow_split_info,
    7280                 :            :                         struct rte_flow_error *error)
    7281                 :            : {
    7282                 :            :         int ret;
    7283                 :            : 
    7284                 :          0 :         ret = flow_create_split_sample(dev, flow, attr, items,
    7285                 :            :                                        actions, flow_split_info, error);
    7286                 :            :         MLX5_ASSERT(ret <= 0);
    7287                 :            :         return ret;
    7288                 :            : }
    7289                 :            : 
    7290                 :            : static inline struct mlx5_flow_tunnel *
    7291                 :            : flow_tunnel_from_rule(const struct mlx5_flow *flow)
    7292                 :            : {
    7293                 :            :         struct mlx5_flow_tunnel *tunnel;
    7294                 :            : 
    7295                 :          0 :         tunnel = RTE_PTR_UNQUAL(flow->tunnel);
    7296                 :            : 
    7297                 :            :         return tunnel;
    7298                 :            : }
    7299                 :            : 
    7300                 :            : /**
    7301                 :            :  * Create a flow and add it to @p list.
    7302                 :            :  *
    7303                 :            :  * @param dev
    7304                 :            :  *   Pointer to Ethernet device.
    7305                 :            :  * @param list
    7306                 :            :  *   Pointer to a TAILQ flow list. If this parameter NULL,
    7307                 :            :  *   no list insertion occurred, flow is just created,
    7308                 :            :  *   this is caller's responsibility to track the
    7309                 :            :  *   created flow.
    7310                 :            :  * @param[in] attr
    7311                 :            :  *   Flow rule attributes.
    7312                 :            :  * @param[in] items
    7313                 :            :  *   Pattern specification (list terminated by the END pattern item).
    7314                 :            :  * @param[in] actions
    7315                 :            :  *   Associated actions (list terminated by the END action).
    7316                 :            :  * @param[in] external
    7317                 :            :  *   This flow rule is created by request external to PMD.
    7318                 :            :  * @param[out] error
    7319                 :            :  *   Perform verbose error reporting if not NULL.
    7320                 :            :  *
    7321                 :            :  * @return
    7322                 :            :  *   A flow index on success, 0 otherwise and rte_errno is set.
    7323                 :            :  */
    7324                 :            : uintptr_t
    7325                 :          0 : flow_legacy_list_create(struct rte_eth_dev *dev, enum mlx5_flow_type type,
    7326                 :            :                     const struct rte_flow_attr *attr,
    7327                 :            :                     const struct rte_flow_item items[],
    7328                 :            :                     const struct rte_flow_action original_actions[],
    7329                 :            :                     bool external, struct rte_flow_error *error)
    7330                 :            : {
    7331                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7332                 :            :         struct rte_flow *flow = NULL;
    7333                 :            :         struct mlx5_flow *dev_flow;
    7334                 :            :         const struct rte_flow_action_rss *rss = NULL;
    7335                 :            :         struct mlx5_translated_action_handle
    7336                 :            :                 indir_actions[MLX5_MAX_INDIRECT_ACTIONS];
    7337                 :          0 :         int indir_actions_n = MLX5_MAX_INDIRECT_ACTIONS;
    7338                 :            :         union {
    7339                 :            :                 struct mlx5_flow_expand_rss buf;
    7340                 :            :                 uint8_t buffer[8192];
    7341                 :            :         } expand_buffer;
    7342                 :            :         union {
    7343                 :            :                 struct rte_flow_action actions[MLX5_MAX_SPLIT_ACTIONS];
    7344                 :            :                 uint8_t buffer[2048];
    7345                 :            :         } actions_rx;
    7346                 :            :         union {
    7347                 :            :                 struct rte_flow_action actions[MLX5_MAX_SPLIT_ACTIONS];
    7348                 :            :                 uint8_t buffer[2048];
    7349                 :            :         } actions_hairpin_tx;
    7350                 :            :         union {
    7351                 :            :                 struct rte_flow_item items[MLX5_MAX_SPLIT_ITEMS];
    7352                 :            :                 uint8_t buffer[2048];
    7353                 :            :         } items_tx;
    7354                 :            :         struct mlx5_rte_flow_item_sq sq_specs[RTE_MAX_QUEUES_PER_PORT];
    7355                 :            :         struct mlx5_flow_expand_rss *buf = &expand_buffer.buf;
    7356                 :            :         struct mlx5_flow_rss_desc *rss_desc;
    7357                 :            :         const struct rte_flow_action *p_actions_rx;
    7358                 :            :         uint32_t i;
    7359                 :          0 :         uint32_t idx = 0;
    7360                 :            :         int hairpin_flow;
    7361                 :          0 :         struct rte_flow_attr attr_tx = { .priority = 0 };
    7362                 :            :         const struct rte_flow_action *actions;
    7363                 :          0 :         struct rte_flow_action *translated_actions = NULL;
    7364                 :            :         struct mlx5_flow_tunnel *tunnel;
    7365                 :          0 :         struct tunnel_default_miss_ctx default_miss_ctx = { 0, };
    7366                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_push_thread_workspace();
    7367                 :          0 :         struct mlx5_flow_split_info flow_split_info = {
    7368                 :            :                 .external = !!external,
    7369                 :            :                 .skip_scale = 0,
    7370                 :            :                 .flow_idx = 0,
    7371                 :            :                 .prefix_mark = 0,
    7372                 :            :                 .prefix_layers = 0,
    7373                 :            :                 .table_id = 0
    7374                 :            :         };
    7375                 :            :         int ret;
    7376                 :            :         struct mlx5_shared_action_rss *shared_rss_action;
    7377                 :            : 
    7378         [ #  # ]:          0 :         if (!wks)
    7379                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
    7380                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    7381                 :            :                                           NULL,
    7382                 :            :                                           "failed to push flow workspace");
    7383                 :            :         memset(indir_actions, 0, sizeof(indir_actions));
    7384                 :          0 :         rss_desc = &wks->rss_desc;
    7385                 :          0 :         ret = flow_action_handles_translate(dev, original_actions,
    7386                 :            :                                             indir_actions,
    7387                 :            :                                             &indir_actions_n,
    7388                 :            :                                             &translated_actions, error);
    7389         [ #  # ]:          0 :         if (ret < 0) {
    7390                 :            :                 MLX5_ASSERT(translated_actions == NULL);
    7391                 :            :                 return 0;
    7392                 :            :         }
    7393         [ #  # ]:          0 :         actions = translated_actions ? translated_actions : original_actions;
    7394                 :            :         p_actions_rx = actions;
    7395                 :          0 :         hairpin_flow = flow_check_hairpin_split(dev, attr, actions);
    7396                 :          0 :         ret = flow_drv_validate(dev, attr, items, p_actions_rx,
    7397                 :            :                                 external, hairpin_flow, error);
    7398         [ #  # ]:          0 :         if (ret < 0)
    7399                 :          0 :                 goto error_before_hairpin_split;
    7400                 :          0 :         flow = mlx5_ipool_zmalloc(priv->flows[type], &idx);
    7401         [ #  # ]:          0 :         if (!flow) {
    7402                 :          0 :                 rte_errno = ENOMEM;
    7403                 :          0 :                 goto error_before_hairpin_split;
    7404                 :            :         }
    7405         [ #  # ]:          0 :         if (hairpin_flow > 0) {
    7406         [ #  # ]:          0 :                 if (hairpin_flow > MLX5_MAX_SPLIT_ACTIONS) {
    7407                 :          0 :                         rte_errno = EINVAL;
    7408                 :          0 :                         goto error_before_hairpin_split;
    7409                 :            :                 }
    7410                 :          0 :                 flow_hairpin_split(dev, actions, actions_rx.actions,
    7411                 :            :                                    actions_hairpin_tx.actions, items_tx.items,
    7412                 :            :                                    idx);
    7413                 :            :                 p_actions_rx = actions_rx.actions;
    7414                 :            :         }
    7415                 :          0 :         flow_split_info.flow_idx = idx;
    7416         [ #  # ]:          0 :         flow->drv_type = flow_get_drv_type(dev, attr);
    7417                 :            :         MLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN &&
    7418                 :            :                     flow->drv_type < MLX5_FLOW_TYPE_MAX);
    7419                 :            :         memset(rss_desc, 0, offsetof(struct mlx5_flow_rss_desc, queue));
    7420                 :            :         /* RSS Action only works on NIC RX domain */
    7421         [ #  # ]:          0 :         if (attr->ingress)
    7422                 :          0 :                 rss = flow_get_rss_action(dev, p_actions_rx);
    7423         [ #  # ]:          0 :         if (rss) {
    7424                 :            :                 MLX5_ASSERT(rss->queue_num <= RTE_ETH_RSS_RETA_SIZE_512);
    7425                 :          0 :                 rss_desc->symmetric_hash_function = MLX5_RSS_IS_SYMM(rss->func);
    7426                 :            :                 /*
    7427                 :            :                  * The following information is required by
    7428                 :            :                  * mlx5_flow_hashfields_adjust() in advance.
    7429                 :            :                  */
    7430                 :          0 :                 rss_desc->level = rss->level;
    7431                 :            :                 /* RSS type 0 indicates default RSS type (RTE_ETH_RSS_IP). */
    7432         [ #  # ]:          0 :                 rss_desc->types = !rss->types ? RTE_ETH_RSS_IP : rss->types;
    7433                 :            :         }
    7434                 :          0 :         flow->dev_handles = 0;
    7435   [ #  #  #  # ]:          0 :         if (rss && rss->types) {
    7436                 :            :                 unsigned int graph_root;
    7437                 :            : 
    7438                 :          0 :                 graph_root = find_graph_root(rss->level);
    7439                 :          0 :                 ret = mlx5_flow_expand_rss(buf, sizeof(expand_buffer.buffer),
    7440                 :            :                                            items, rss->types,
    7441                 :            :                                            mlx5_support_expansion, graph_root);
    7442                 :            :                 MLX5_ASSERT(ret > 0 &&
    7443                 :            :                        (unsigned int)ret < sizeof(expand_buffer.buffer));
    7444         [ #  # ]:          0 :                 if (rte_log_can_log(mlx5_logtype, RTE_LOG_DEBUG)) {
    7445         [ #  # ]:          0 :                         for (i = 0; i < buf->entries; ++i)
    7446                 :          0 :                                 mlx5_dbg__print_pattern(buf->entry[i].pattern);
    7447                 :            :                 }
    7448                 :            :         } else {
    7449                 :          0 :                 ret = mlx5_flow_expand_sqn((struct mlx5_flow_expand_sqn *)buf,
    7450                 :            :                                            sizeof(expand_buffer.buffer),
    7451                 :            :                                            items, sq_specs);
    7452         [ #  # ]:          0 :                 if (ret) {
    7453                 :          0 :                         rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
    7454                 :            :                                            NULL, "not enough memory for rte_flow");
    7455                 :          0 :                         goto error;
    7456                 :            :                 }
    7457         [ #  # ]:          0 :                 if (buf->entries == 0) {
    7458                 :          0 :                         buf->entries = 1;
    7459                 :          0 :                         buf->entry[0].pattern = (void *)(uintptr_t)items;
    7460                 :            :                 }
    7461                 :            :         }
    7462                 :          0 :         rss_desc->shared_rss = flow_get_shared_rss_action(dev, indir_actions,
    7463                 :            :                                                       indir_actions_n);
    7464         [ #  # ]:          0 :         for (i = 0; i < buf->entries; ++i) {
    7465                 :            :                 /* Initialize flow split data. */
    7466                 :          0 :                 flow_split_info.prefix_layers = 0;
    7467                 :          0 :                 flow_split_info.prefix_mark = 0;
    7468                 :          0 :                 flow_split_info.skip_scale = 0;
    7469                 :            :                 /*
    7470                 :            :                  * The splitter may create multiple dev_flows,
    7471                 :            :                  * depending on configuration. In the simplest
    7472                 :            :                  * case it just creates unmodified original flow.
    7473                 :            :                  */
    7474                 :            :                 ret = flow_create_split_outer(dev, flow, attr,
    7475                 :          0 :                                               buf->entry[i].pattern,
    7476                 :            :                                               p_actions_rx, &flow_split_info,
    7477                 :            :                                               error);
    7478         [ #  # ]:          0 :                 if (ret < 0)
    7479                 :          0 :                         goto error;
    7480         [ #  # ]:          0 :                 if (is_flow_tunnel_steer_rule(wks->flows[0].tof_type)) {
    7481                 :          0 :                         ret = flow_tunnel_add_default_miss(dev, flow, attr,
    7482                 :            :                                                            p_actions_rx,
    7483                 :            :                                                            idx,
    7484                 :            :                                                            wks->flows[0].tunnel,
    7485                 :            :                                                            &default_miss_ctx,
    7486                 :            :                                                            error);
    7487         [ #  # ]:          0 :                         if (ret < 0) {
    7488                 :          0 :                                 mlx5_free(default_miss_ctx.queue);
    7489                 :          0 :                                 goto error;
    7490                 :            :                         }
    7491                 :            :                 }
    7492                 :            :         }
    7493                 :            :         /* Create the tx flow. */
    7494         [ #  # ]:          0 :         if (hairpin_flow) {
    7495                 :          0 :                 attr_tx.group = MLX5_HAIRPIN_TX_TABLE;
    7496                 :          0 :                 attr_tx.ingress = 0;
    7497                 :          0 :                 attr_tx.egress = 1;
    7498                 :          0 :                 dev_flow = flow_drv_prepare(dev, flow, &attr_tx, items_tx.items,
    7499                 :            :                                          actions_hairpin_tx.actions,
    7500                 :            :                                          idx, error);
    7501         [ #  # ]:          0 :                 if (!dev_flow)
    7502                 :          0 :                         goto error;
    7503                 :          0 :                 dev_flow->flow = flow;
    7504                 :          0 :                 dev_flow->external = 0;
    7505                 :          0 :                 SILIST_INSERT(&flow->dev_handles, dev_flow->handle_idx,
    7506                 :            :                               dev_flow->handle, next);
    7507                 :            :                 ret = flow_drv_translate(dev, dev_flow, &attr_tx,
    7508                 :            :                                          items_tx.items,
    7509                 :            :                                          actions_hairpin_tx.actions, error);
    7510         [ #  # ]:          0 :                 if (ret < 0)
    7511                 :          0 :                         goto error;
    7512                 :            :         }
    7513                 :            :         /*
    7514                 :            :          * Update the metadata register copy table. If extensive
    7515                 :            :          * metadata feature is enabled and registers are supported
    7516                 :            :          * we might create the extra rte_flow for each unique
    7517                 :            :          * MARK/FLAG action ID.
    7518                 :            :          *
    7519                 :            :          * The table is updated for ingress and transfer flows only, because
    7520                 :            :          * the egress Flows belong to the different device and
    7521                 :            :          * copy table should be updated in peer NIC Rx domain.
    7522                 :            :          */
    7523   [ #  #  #  # ]:          0 :         if ((attr->ingress || attr->transfer) &&
    7524         [ #  # ]:          0 :             (external || attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP)) {
    7525                 :          0 :                 ret = flow_mreg_update_copy_table(dev, flow, actions, error);
    7526         [ #  # ]:          0 :                 if (ret)
    7527                 :          0 :                         goto error;
    7528                 :            :         }
    7529                 :            :         /*
    7530                 :            :          * If the flow is external (from application) OR device is started,
    7531                 :            :          * OR mreg discover, then apply immediately.
    7532                 :            :          */
    7533   [ #  #  #  # ]:          0 :         if (external || dev->data->dev_started ||
    7534         [ #  # ]:          0 :             (attr->group == MLX5_FLOW_MREG_CP_TABLE_GROUP &&
    7535         [ #  # ]:          0 :              attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR)) {
    7536                 :            :                 ret = flow_drv_apply(dev, flow, error);
    7537         [ #  # ]:          0 :                 if (ret < 0)
    7538                 :          0 :                         goto error;
    7539                 :            :         }
    7540                 :          0 :         flow->type = type;
    7541                 :          0 :         flow_rxq_flags_set(dev, flow);
    7542                 :          0 :         rte_free(translated_actions);
    7543                 :            :         tunnel = flow_tunnel_from_rule(wks->flows);
    7544         [ #  # ]:          0 :         if (tunnel) {
    7545                 :          0 :                 flow->tunnel = 1;
    7546                 :          0 :                 flow->tunnel_id = tunnel->tunnel_id;
    7547                 :          0 :                 rte_atomic_fetch_add_explicit(&tunnel->refctn, 1, rte_memory_order_relaxed);
    7548                 :          0 :                 mlx5_free(default_miss_ctx.queue);
    7549                 :            :         }
    7550                 :          0 :         mlx5_flow_pop_thread_workspace();
    7551                 :          0 :         return idx;
    7552                 :          0 : error:
    7553                 :            :         MLX5_ASSERT(flow);
    7554                 :          0 :         ret = rte_errno; /* Save rte_errno before cleanup. */
    7555                 :          0 :         flow_mreg_del_copy_action(dev, flow);
    7556                 :            :         flow_drv_destroy(dev, flow);
    7557                 :            : 
    7558         [ #  # ]:          0 :         if (rss_desc->shared_rss) {
    7559                 :            :                 shared_rss_action = (struct mlx5_shared_action_rss *)
    7560                 :          0 :                         mlx5_ipool_get
    7561                 :          0 :                         (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
    7562                 :            :                         rss_desc->shared_rss);
    7563         [ #  # ]:          0 :                 if (shared_rss_action)
    7564                 :          0 :                         rte_atomic_fetch_sub_explicit(&(shared_rss_action)->refcnt, 1,
    7565                 :            :                                                       rte_memory_order_relaxed);
    7566                 :            :         }
    7567                 :          0 :         mlx5_ipool_free(priv->flows[type], idx);
    7568                 :          0 :         rte_errno = ret; /* Restore rte_errno. */
    7569                 :            :         ret = rte_errno;
    7570                 :            :         rte_errno = ret;
    7571                 :          0 : error_before_hairpin_split:
    7572                 :          0 :         mlx5_flow_pop_thread_workspace();
    7573                 :          0 :         rte_free(translated_actions);
    7574                 :          0 :         return 0;
    7575                 :            : }
    7576                 :            : 
    7577                 :            : /**
    7578                 :            :  * Create a dedicated flow rule on e-switch table 0 (root table), to direct all
    7579                 :            :  * incoming packets to table 1.
    7580                 :            :  *
    7581                 :            :  * Other flow rules, requested for group n, will be created in
    7582                 :            :  * e-switch table n+1.
    7583                 :            :  * Jump action to e-switch group n will be created to group n+1.
    7584                 :            :  *
    7585                 :            :  * Used when working in switchdev mode, to utilise advantages of table 1
    7586                 :            :  * and above.
    7587                 :            :  *
    7588                 :            :  * @param dev
    7589                 :            :  *   Pointer to Ethernet device.
    7590                 :            :  *
    7591                 :            :  * @return
    7592                 :            :  *   Pointer to flow on success, NULL otherwise and rte_errno is set.
    7593                 :            :  */
    7594                 :            : struct rte_flow *
    7595                 :          0 : mlx5_flow_create_esw_table_zero_flow(struct rte_eth_dev *dev)
    7596                 :            : {
    7597                 :          0 :         const struct rte_flow_attr attr = {
    7598                 :            :                 .group = 0,
    7599                 :            :                 .priority = 0,
    7600                 :            :                 .ingress = 0,
    7601                 :            :                 .egress = 0,
    7602                 :            :                 .transfer = 1,
    7603                 :            :         };
    7604                 :          0 :         const struct rte_flow_item pattern = {
    7605                 :            :                 .type = RTE_FLOW_ITEM_TYPE_END,
    7606                 :            :         };
    7607                 :          0 :         struct rte_flow_action_jump jump = {
    7608                 :            :                 .group = 1,
    7609                 :            :         };
    7610                 :          0 :         const struct rte_flow_action actions[] = {
    7611                 :            :                 {
    7612                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
    7613                 :            :                         .conf = &jump,
    7614                 :            :                 },
    7615                 :            :                 {
    7616                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
    7617                 :            :                 },
    7618                 :            :         };
    7619                 :            :         struct rte_flow_error error;
    7620                 :            : 
    7621                 :          0 :         return (void *)(uintptr_t)mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_CTL,
    7622                 :            :                                                    &attr, &pattern,
    7623                 :            :                                                    actions, false, &error);
    7624                 :            : }
    7625                 :            : 
    7626                 :            : /**
    7627                 :            :  * Create a dedicated flow rule on e-switch table 1, matches ESW manager
    7628                 :            :  * and sq number, directs all packets to peer vport.
    7629                 :            :  *
    7630                 :            :  * @param dev
    7631                 :            :  *   Pointer to Ethernet device.
    7632                 :            :  * @param sq_num
    7633                 :            :  *   SQ number.
    7634                 :            :  *
    7635                 :            :  * @return
    7636                 :            :  *   Flow ID on success, 0 otherwise and rte_errno is set.
    7637                 :            :  */
    7638                 :            : uint32_t
    7639                 :          0 : mlx5_flow_create_devx_sq_miss_flow(struct rte_eth_dev *dev, uint32_t sq_num)
    7640                 :            : {
    7641                 :          0 :         struct rte_flow_attr attr = {
    7642                 :            :                 .group = 0,
    7643                 :            :                 .priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR,
    7644                 :            :                 .ingress = 0,
    7645                 :            :                 .egress = 0,
    7646                 :            :                 .transfer = 1,
    7647                 :            :         };
    7648                 :          0 :         struct rte_flow_item_port_id port_spec = {
    7649                 :            :                 .id = MLX5_PORT_ESW_MGR,
    7650                 :            :         };
    7651                 :          0 :         struct mlx5_rte_flow_item_sq sq_spec = {
    7652                 :            :                 .queue = sq_num,
    7653                 :            :         };
    7654                 :          0 :         struct rte_flow_item pattern[] = {
    7655                 :            :                 {
    7656                 :            :                         .type = RTE_FLOW_ITEM_TYPE_PORT_ID,
    7657                 :            :                         .spec = &port_spec,
    7658                 :            :                 },
    7659                 :            :                 {
    7660                 :            :                         .type = (enum rte_flow_item_type)
    7661                 :            :                                 MLX5_RTE_FLOW_ITEM_TYPE_SQ,
    7662                 :            :                         .spec = &sq_spec,
    7663                 :            :                 },
    7664                 :            :                 {
    7665                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    7666                 :            :                 },
    7667                 :            :         };
    7668                 :          0 :         struct rte_flow_action_jump jump = {
    7669                 :            :                 .group = 1,
    7670                 :            :         };
    7671                 :          0 :         struct rte_flow_action_port_id port = {
    7672                 :          0 :                 .id = dev->data->port_id,
    7673                 :            :         };
    7674                 :          0 :         struct rte_flow_action actions[] = {
    7675                 :            :                 {
    7676                 :            :                         .type = RTE_FLOW_ACTION_TYPE_JUMP,
    7677                 :            :                         .conf = &jump,
    7678                 :            :                 },
    7679                 :            :                 {
    7680                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
    7681                 :            :                 },
    7682                 :            :         };
    7683                 :            :         struct rte_flow_error error;
    7684                 :            : 
    7685                 :            :         /*
    7686                 :            :          * Creates group 0, highest priority jump flow.
    7687                 :            :          * Matches txq to bypass kernel packets.
    7688                 :            :          */
    7689         [ #  # ]:          0 :         if (mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_CTL, &attr, pattern, actions,
    7690                 :            :                              false, &error) == 0)
    7691                 :            :                 return 0;
    7692                 :            :         /* Create group 1, lowest priority redirect flow for txq. */
    7693                 :          0 :         attr.group = 1;
    7694                 :          0 :         actions[0].conf = &port;
    7695                 :          0 :         actions[0].type = RTE_FLOW_ACTION_TYPE_PORT_ID;
    7696                 :          0 :         return mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_CTL, &attr, pattern,
    7697                 :            :                                 actions, false, &error);
    7698                 :            : }
    7699                 :            : 
    7700                 :            : /**
    7701                 :            :  * Validate a flow supported by the NIC.
    7702                 :            :  *
    7703                 :            :  * @see rte_flow_validate()
    7704                 :            :  * @see rte_flow_ops
    7705                 :            :  */
    7706                 :            : int
    7707                 :          0 : mlx5_flow_validate(struct rte_eth_dev *dev,
    7708                 :            :                    const struct rte_flow_attr *attr,
    7709                 :            :                    const struct rte_flow_item items[],
    7710                 :            :                    const struct rte_flow_action original_actions[],
    7711                 :            :                    struct rte_flow_error *error)
    7712                 :            : {
    7713                 :            :         int hairpin_flow;
    7714                 :            :         struct mlx5_translated_action_handle
    7715                 :            :                 indir_actions[MLX5_MAX_INDIRECT_ACTIONS];
    7716                 :          0 :         int indir_actions_n = MLX5_MAX_INDIRECT_ACTIONS;
    7717                 :            :         const struct rte_flow_action *actions;
    7718                 :          0 :         struct rte_flow_action *translated_actions = NULL;
    7719                 :          0 :         int ret = flow_action_handles_translate(dev, original_actions,
    7720                 :            :                                                 indir_actions,
    7721                 :            :                                                 &indir_actions_n,
    7722                 :            :                                                 &translated_actions, error);
    7723                 :            : 
    7724         [ #  # ]:          0 :         if (ret)
    7725                 :            :                 return ret;
    7726         [ #  # ]:          0 :         actions = translated_actions ? translated_actions : original_actions;
    7727                 :          0 :         hairpin_flow = flow_check_hairpin_split(dev, attr, actions);
    7728                 :          0 :         ret = flow_drv_validate(dev, attr, items, actions,
    7729                 :            :                                 true, hairpin_flow, error);
    7730                 :          0 :         rte_free(translated_actions);
    7731                 :          0 :         return ret;
    7732                 :            : }
    7733                 :            : 
    7734                 :            : static int
    7735                 :          0 : mlx5_flow_cache_flow_info(struct rte_eth_dev *dev,
    7736                 :            :                           const struct rte_flow_attr *attr,
    7737                 :            :                           const uint32_t orig_prio,
    7738                 :            :                           const struct rte_flow_item *items,
    7739                 :            :                           const struct rte_flow_action *actions,
    7740                 :            :                           uint32_t flow_idx)
    7741                 :            : {
    7742                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7743                 :            :         struct rte_pmd_mlx5_flow_engine_mode_info *mode_info = &priv->mode_info;
    7744                 :            :         struct mlx5_dv_flow_info *flow_info, *tmp_info;
    7745                 :            :         struct rte_flow_error error;
    7746                 :            :         int len, ret;
    7747                 :            : 
    7748                 :          0 :         flow_info = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*flow_info), 0, SOCKET_ID_ANY);
    7749         [ #  # ]:          0 :         if (!flow_info) {
    7750                 :          0 :                 DRV_LOG(ERR, "No enough memory for flow_info caching.");
    7751                 :          0 :                 return -1;
    7752                 :            :         }
    7753                 :          0 :         flow_info->orig_prio = orig_prio;
    7754                 :          0 :         flow_info->attr = *attr;
    7755                 :            :         /* Standby mode rule awlays saves it in low priority entry. */
    7756                 :          0 :         flow_info->flow_idx_low_prio = flow_idx;
    7757                 :            : 
    7758                 :            :         /* Store matching items. */
    7759                 :          0 :         ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, NULL, 0, items, &error);
    7760         [ #  # ]:          0 :         if (ret <= 0) {
    7761                 :          0 :                 DRV_LOG(ERR, "Can't get items length.");
    7762                 :          0 :                 goto end;
    7763                 :            :         }
    7764                 :          0 :         len = RTE_ALIGN(ret, 16);
    7765                 :          0 :         flow_info->items = mlx5_malloc(MLX5_MEM_ZERO, len, 0, SOCKET_ID_ANY);
    7766         [ #  # ]:          0 :         if (!flow_info->items) {
    7767                 :          0 :                 DRV_LOG(ERR, "No enough memory for items caching.");
    7768                 :          0 :                 goto end;
    7769                 :            :         }
    7770                 :          0 :         ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, flow_info->items, ret, items, &error);
    7771         [ #  # ]:          0 :         if (ret <= 0) {
    7772                 :          0 :                 DRV_LOG(ERR, "Can't duplicate items.");
    7773                 :          0 :                 goto end;
    7774                 :            :         }
    7775                 :            : 
    7776                 :            :         /* Store flow actions. */
    7777                 :          0 :         ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, actions, &error);
    7778         [ #  # ]:          0 :         if (ret <= 0) {
    7779                 :          0 :                 DRV_LOG(ERR, "Can't get actions length.");
    7780                 :          0 :                 goto end;
    7781                 :            :         }
    7782                 :          0 :         len = RTE_ALIGN(ret, 16);
    7783                 :          0 :         flow_info->actions = mlx5_malloc(MLX5_MEM_ZERO, len, 0, SOCKET_ID_ANY);
    7784         [ #  # ]:          0 :         if (!flow_info->actions) {
    7785                 :          0 :                 DRV_LOG(ERR, "No enough memory for actions caching.");
    7786                 :          0 :                 goto end;
    7787                 :            :         }
    7788                 :          0 :         ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, flow_info->actions, ret, actions, &error);
    7789         [ #  # ]:          0 :         if (ret <= 0) {
    7790                 :          0 :                 DRV_LOG(ERR, "Can't duplicate actions.");
    7791                 :          0 :                 goto end;
    7792                 :            :         }
    7793                 :            : 
    7794                 :            :         /* Insert to the list end. */
    7795         [ #  # ]:          0 :         if (LIST_EMPTY(&mode_info->hot_upgrade)) {
    7796                 :          0 :                 LIST_INSERT_HEAD(&mode_info->hot_upgrade, flow_info,  next);
    7797                 :            :         } else {
    7798                 :            :                 tmp_info = LIST_FIRST(&mode_info->hot_upgrade);
    7799         [ #  # ]:          0 :                 while (LIST_NEXT(tmp_info, next))
    7800                 :            :                         tmp_info = LIST_NEXT(tmp_info, next);
    7801                 :          0 :                 LIST_INSERT_AFTER(tmp_info, flow_info, next);
    7802                 :            :         }
    7803                 :            :         return 0;
    7804                 :          0 : end:
    7805         [ #  # ]:          0 :         if (flow_info->items)
    7806                 :          0 :                 mlx5_free(flow_info->items);
    7807         [ #  # ]:          0 :         if (flow_info->actions)
    7808                 :          0 :                 mlx5_free(flow_info->actions);
    7809                 :          0 :         mlx5_free(flow_info);
    7810                 :          0 :         return -1;
    7811                 :            : }
    7812                 :            : 
    7813                 :            : static int
    7814                 :          0 : mlx5_flow_cache_flow_toggle(struct rte_eth_dev *dev, bool orig_prio)
    7815                 :            : {
    7816                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7817                 :            :         struct rte_pmd_mlx5_flow_engine_mode_info *mode_info = &priv->mode_info;
    7818                 :            :         struct mlx5_dv_flow_info *flow_info;
    7819                 :            :         struct rte_flow_attr attr;
    7820                 :            :         struct rte_flow_error error;
    7821                 :            :         struct rte_flow *high, *low;
    7822                 :            : 
    7823                 :          0 :         flow_info = LIST_FIRST(&mode_info->hot_upgrade);
    7824         [ #  # ]:          0 :         while (flow_info) {
    7825                 :            :                 /* DUP flow may have the same priority. */
    7826         [ #  # ]:          0 :                 if (flow_info->orig_prio != flow_info->attr.priority) {
    7827                 :          0 :                         attr = flow_info->attr;
    7828         [ #  # ]:          0 :                         if (orig_prio)
    7829                 :          0 :                                 attr.priority = flow_info->orig_prio;
    7830                 :          0 :                         flow_info->flow_idx_high_prio = mlx5_flow_list_create(dev,
    7831                 :            :                                         MLX5_FLOW_TYPE_GEN, &attr,
    7832                 :          0 :                                         flow_info->items, flow_info->actions,
    7833                 :            :                                         true, &error);
    7834         [ #  # ]:          0 :                         if (!flow_info->flow_idx_high_prio) {
    7835                 :          0 :                                 DRV_LOG(ERR, "Priority toggle failed internally.");
    7836                 :          0 :                                 goto err;
    7837                 :            :                         }
    7838                 :            :                 }
    7839                 :          0 :                 flow_info = LIST_NEXT(flow_info, next);
    7840                 :            :         }
    7841                 :            :         /* Delete the low priority rules and swap the flow handle. */
    7842                 :          0 :         flow_info = LIST_FIRST(&mode_info->hot_upgrade);
    7843         [ #  # ]:          0 :         while (flow_info) {
    7844                 :            :                 MLX5_ASSERT(flow_info->flow_idx_low_prio);
    7845         [ #  # ]:          0 :                 if (flow_info->orig_prio != flow_info->attr.priority) {
    7846                 :          0 :                         high = mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN],
    7847                 :            :                                         flow_info->flow_idx_high_prio);
    7848                 :          0 :                         low = mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN],
    7849                 :            :                                         flow_info->flow_idx_low_prio);
    7850         [ #  # ]:          0 :                         if (high && low) {
    7851                 :          0 :                                 RTE_SWAP(*low, *high);
    7852                 :          0 :                                 mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN,
    7853                 :          0 :                                                   flow_info->flow_idx_low_prio);
    7854                 :          0 :                                 flow_info->flow_idx_high_prio = 0;
    7855                 :            :                         }
    7856                 :            :                 }
    7857                 :          0 :                 flow_info = LIST_NEXT(flow_info, next);
    7858                 :            :         }
    7859                 :            :         return 0;
    7860                 :            : err:
    7861                 :            :         /* Destroy preceding successful high priority rules. */
    7862                 :          0 :         flow_info = LIST_FIRST(&mode_info->hot_upgrade);
    7863         [ #  # ]:          0 :         while (flow_info) {
    7864         [ #  # ]:          0 :                 if (flow_info->orig_prio != flow_info->attr.priority) {
    7865         [ #  # ]:          0 :                         if (flow_info->flow_idx_high_prio)
    7866                 :          0 :                                 mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN,
    7867                 :            :                                                   flow_info->flow_idx_high_prio);
    7868                 :            :                         else
    7869                 :            :                                 break;
    7870                 :          0 :                         flow_info->flow_idx_high_prio = 0;
    7871                 :            :                 }
    7872                 :          0 :                 flow_info = LIST_NEXT(flow_info, next);
    7873                 :            :         }
    7874                 :            :         return -1;
    7875                 :            : }
    7876                 :            : 
    7877                 :            : /**
    7878                 :            :  * Set the mode of the flow engine of a process to active or standby during live migration.
    7879                 :            :  *
    7880                 :            :  * @param[in] mode
    7881                 :            :  *   MLX5 flow engine mode, @see `enum rte_pmd_mlx5_flow_engine_mode`.
    7882                 :            :  * @param[in] flags
    7883                 :            :  *   Flow engine mode specific flags.
    7884                 :            :  *
    7885                 :            :  * @return
    7886                 :            :  *   Negative value on error, positive on success.
    7887                 :            :  */
    7888                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_flow_engine_set_mode, 23.03)
    7889                 :            : int
    7890                 :          0 : rte_pmd_mlx5_flow_engine_set_mode(enum rte_pmd_mlx5_flow_engine_mode mode, uint32_t flags)
    7891                 :            : {
    7892                 :            :         struct mlx5_priv *priv;
    7893                 :            :         struct rte_pmd_mlx5_flow_engine_mode_info *mode_info;
    7894                 :            :         struct mlx5_dv_flow_info *flow_info, *tmp_info;
    7895                 :            :         uint16_t port, port_id;
    7896                 :            :         uint16_t toggle_num = 0;
    7897                 :            :         struct rte_eth_dev *dev;
    7898                 :            :         enum rte_pmd_mlx5_flow_engine_mode orig_mode;
    7899                 :            :         uint32_t orig_flags;
    7900                 :            :         bool need_toggle = false;
    7901                 :            : 
    7902                 :            :         /* Check if flags combinations are supported. */
    7903         [ #  # ]:          0 :         if (flags && flags != RTE_PMD_MLX5_FLOW_ENGINE_FLAG_STANDBY_DUP_INGRESS) {
    7904                 :          0 :                 DRV_LOG(ERR, "Doesn't support such flags %u", flags);
    7905                 :          0 :                 return -1;
    7906                 :            :         }
    7907         [ #  # ]:          0 :         MLX5_ETH_FOREACH_DEV(port, NULL) {
    7908                 :          0 :                 dev = &rte_eth_devices[port];
    7909                 :          0 :                 priv = dev->data->dev_private;
    7910                 :            :                 mode_info = &priv->mode_info;
    7911                 :            :                 /* No mode change. Assume all devices hold the same mode. */
    7912         [ #  # ]:          0 :                 if (mode_info->mode == mode) {
    7913                 :          0 :                         DRV_LOG(INFO, "Process flow engine has been in mode %u", mode);
    7914   [ #  #  #  # ]:          0 :                         if (mode_info->mode_flag != flags && !LIST_EMPTY(&mode_info->hot_upgrade)) {
    7915                 :          0 :                                 DRV_LOG(ERR, "Port %u has rule cache with different flag %u\n",
    7916                 :            :                                                 port, mode_info->mode_flag);
    7917                 :          0 :                                 orig_mode = mode_info->mode;
    7918                 :          0 :                                 orig_flags = mode_info->mode_flag;
    7919                 :          0 :                                 goto err;
    7920                 :            :                         }
    7921                 :          0 :                         mode_info->mode_flag = flags;
    7922                 :          0 :                         toggle_num++;
    7923                 :          0 :                         continue;
    7924                 :            :                 }
    7925                 :            :                 /* Active -> standby. */
    7926         [ #  # ]:          0 :                 if (mode == RTE_PMD_MLX5_FLOW_ENGINE_MODE_STANDBY) {
    7927         [ #  # ]:          0 :                         if (!LIST_EMPTY(&mode_info->hot_upgrade)) {
    7928                 :          0 :                                 DRV_LOG(ERR, "Cached rule existed");
    7929                 :          0 :                                 orig_mode = mode_info->mode;
    7930                 :          0 :                                 orig_flags = mode_info->mode_flag;
    7931                 :          0 :                                 goto err;
    7932                 :            :                         }
    7933                 :          0 :                         mode_info->mode_flag = flags;
    7934                 :          0 :                         mode_info->mode = mode;
    7935                 :          0 :                         toggle_num++;
    7936                 :            :                 /* Standby -> active. */
    7937         [ #  # ]:          0 :                 } else if (mode == RTE_PMD_MLX5_FLOW_ENGINE_MODE_ACTIVE) {
    7938         [ #  # ]:          0 :                         if (LIST_EMPTY(&mode_info->hot_upgrade)) {
    7939                 :          0 :                                 DRV_LOG(INFO, "No cached rule existed");
    7940                 :            :                         } else {
    7941         [ #  # ]:          0 :                                 if (mlx5_flow_cache_flow_toggle(dev, true)) {
    7942                 :          0 :                                         orig_mode = mode_info->mode;
    7943                 :          0 :                                         orig_flags = mode_info->mode_flag;
    7944                 :            :                                         need_toggle = true;
    7945                 :          0 :                                         goto err;
    7946                 :            :                                 }
    7947                 :            :                         }
    7948                 :          0 :                         toggle_num++;
    7949                 :            :                 }
    7950                 :            :         }
    7951         [ #  # ]:          0 :         if (mode == RTE_PMD_MLX5_FLOW_ENGINE_MODE_ACTIVE) {
    7952                 :            :                 /* Clear cache flow rules. */
    7953         [ #  # ]:          0 :                 MLX5_ETH_FOREACH_DEV(port, NULL) {
    7954                 :          0 :                         priv = rte_eth_devices[port].data->dev_private;
    7955                 :            :                         mode_info = &priv->mode_info;
    7956                 :          0 :                         flow_info = LIST_FIRST(&mode_info->hot_upgrade);
    7957         [ #  # ]:          0 :                         while (flow_info) {
    7958                 :          0 :                                 tmp_info = LIST_NEXT(flow_info, next);
    7959         [ #  # ]:          0 :                                 LIST_REMOVE(flow_info, next);
    7960                 :          0 :                                 mlx5_free(flow_info->actions);
    7961                 :          0 :                                 mlx5_free(flow_info->items);
    7962                 :          0 :                                 mlx5_free(flow_info);
    7963                 :            :                                 flow_info = tmp_info;
    7964                 :            :                         }
    7965                 :            :                         MLX5_ASSERT(LIST_EMPTY(&mode_info->hot_upgrade));
    7966                 :            :                 }
    7967                 :            :         }
    7968                 :          0 :         return toggle_num;
    7969                 :          0 : err:
    7970                 :            :         /* Rollback all preceding successful ports. */
    7971         [ #  # ]:          0 :         MLX5_ETH_FOREACH_DEV(port_id, NULL) {
    7972         [ #  # ]:          0 :                 if (port_id == port)
    7973                 :            :                         break;
    7974                 :          0 :                 priv = rte_eth_devices[port_id].data->dev_private;
    7975                 :            :                 mode_info = &priv->mode_info;
    7976   [ #  #  #  #  :          0 :                 if (need_toggle && !LIST_EMPTY(&mode_info->hot_upgrade) &&
                   #  # ]
    7977                 :          0 :                     mlx5_flow_cache_flow_toggle(dev, false))
    7978                 :            :                         return -EPERM;
    7979                 :          0 :                 mode_info->mode = orig_mode;
    7980                 :          0 :                 mode_info->mode_flag = orig_flags;
    7981                 :            :         }
    7982                 :            :         return -EINVAL;
    7983                 :            : }
    7984                 :            : /**
    7985                 :            :  * Create a flow.
    7986                 :            :  *
    7987                 :            :  * @see rte_flow_create()
    7988                 :            :  * @see rte_flow_ops
    7989                 :            :  */
    7990                 :            : struct rte_flow *
    7991                 :          0 : mlx5_flow_create(struct rte_eth_dev *dev,
    7992                 :            :                  const struct rte_flow_attr *attr,
    7993                 :            :                  const struct rte_flow_item items[],
    7994                 :            :                  const struct rte_flow_action actions[],
    7995                 :            :                  struct rte_flow_error *error)
    7996                 :            : {
    7997                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7998                 :            :         struct rte_flow_attr *new_attr = (void *)(uintptr_t)attr;
    7999                 :          0 :         uint32_t prio = attr->priority;
    8000                 :            :         uintptr_t flow_idx;
    8001                 :            : 
    8002                 :            :         /*
    8003                 :            :          * If the device is not started yet, it is not allowed to created a
    8004                 :            :          * flow from application. PMD default flows and traffic control flows
    8005                 :            :          * are not affected.
    8006                 :            :          */
    8007         [ #  # ]:          0 :         if (unlikely(!dev->data->dev_started)) {
    8008                 :          0 :                 DRV_LOG(DEBUG, "port %u is not started when "
    8009                 :            :                         "inserting a flow", dev->data->port_id);
    8010                 :          0 :                 rte_flow_error_set(error, ENODEV,
    8011                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8012                 :            :                                    NULL,
    8013                 :            :                                    "port not started");
    8014                 :          0 :                 return NULL;
    8015                 :            :         }
    8016         [ #  # ]:          0 :         if (unlikely(mlx5_need_cache_flow(priv, attr))) {
    8017         [ #  # ]:          0 :                 if (attr->transfer ||
    8018   [ #  #  #  # ]:          0 :                                 (attr->ingress && !(priv->mode_info.mode_flag &
    8019                 :            :                                 RTE_PMD_MLX5_FLOW_ENGINE_FLAG_STANDBY_DUP_INGRESS)))
    8020                 :          0 :                         new_attr->priority += 1;
    8021                 :            :         }
    8022                 :          0 :         flow_idx = mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_GEN, attr, items, actions,
    8023                 :            :                 true, error);
    8024         [ #  # ]:          0 :         if (!flow_idx)
    8025                 :            :                 return NULL;
    8026         [ #  # ]:          0 :         if (unlikely(mlx5_need_cache_flow(priv, attr))) {
    8027         [ #  # ]:          0 :                 if (mlx5_flow_cache_flow_info(dev, attr, prio, items, actions, flow_idx)) {
    8028                 :          0 :                         mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN, flow_idx);
    8029                 :            :                         flow_idx = 0;
    8030                 :            :                 }
    8031                 :            :         }
    8032                 :          0 :         return (void *)(uintptr_t)flow_idx;
    8033                 :            : }
    8034                 :            : 
    8035                 :            : uintptr_t
    8036                 :          0 : mlx5_flow_list_create(struct rte_eth_dev *dev, enum mlx5_flow_type type,
    8037                 :            :                       const struct rte_flow_attr *attr,
    8038                 :            :                       const struct rte_flow_item items[],
    8039                 :            :                       const struct rte_flow_action actions[],
    8040                 :            :                       bool external, struct rte_flow_error *error)
    8041                 :            : {
    8042                 :            :         const struct mlx5_flow_driver_ops *fops;
    8043                 :          0 :         enum mlx5_flow_drv_type drv_type = flow_get_drv_type(dev, attr);
    8044                 :            : 
    8045                 :          0 :         fops = flow_get_drv_ops(drv_type);
    8046                 :          0 :         return fops->list_create(dev, type, attr, items, actions, external,
    8047                 :            :                 error);
    8048                 :            : }
    8049                 :            : 
    8050                 :            : /**
    8051                 :            :  * Destroy a flow in a list.
    8052                 :            :  *
    8053                 :            :  * @param dev
    8054                 :            :  *   Pointer to Ethernet device.
    8055                 :            :  * @param[in] flow_idx
    8056                 :            :  *   Index of flow to destroy.
    8057                 :            :  */
    8058                 :            : void
    8059                 :          0 : flow_legacy_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type,
    8060                 :            :                      uintptr_t flow_idx)
    8061                 :            : {
    8062                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8063                 :          0 :         struct rte_flow *flow = mlx5_ipool_get(priv->flows[type], (uint32_t)flow_idx);
    8064                 :            : 
    8065         [ #  # ]:          0 :         if (!flow)
    8066                 :            :                 return;
    8067                 :            :         MLX5_ASSERT((type >= MLX5_FLOW_TYPE_CTL) && (type < MLX5_FLOW_TYPE_MAXI));
    8068                 :            :         MLX5_ASSERT(flow->type == type);
    8069                 :            :         /*
    8070                 :            :          * Update RX queue flags only if port is started, otherwise it is
    8071                 :            :          * already clean.
    8072                 :            :          */
    8073         [ #  # ]:          0 :         if (dev->data->dev_started)
    8074                 :          0 :                 flow_rxq_flags_trim(dev, flow);
    8075                 :            :         flow_drv_destroy(dev, flow);
    8076         [ #  # ]:          0 :         if (flow->tunnel) {
    8077                 :            :                 struct mlx5_flow_tunnel *tunnel;
    8078                 :            : 
    8079                 :          0 :                 tunnel = mlx5_find_tunnel_id(dev, flow->tunnel_id);
    8080                 :          0 :                 RTE_VERIFY(tunnel);
    8081         [ #  # ]:          0 :                 if (!(rte_atomic_fetch_sub_explicit(&tunnel->refctn, 1,
    8082                 :            :                                 rte_memory_order_relaxed) - 1))
    8083                 :          0 :                         mlx5_flow_tunnel_free(dev, tunnel);
    8084                 :            :         }
    8085                 :          0 :         flow_mreg_del_copy_action(dev, flow);
    8086                 :          0 :         mlx5_ipool_free(priv->flows[type], flow_idx);
    8087                 :            : }
    8088                 :            : 
    8089                 :            : void
    8090         [ #  # ]:          0 : mlx5_flow_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type,
    8091                 :            :                        uintptr_t flow_idx)
    8092                 :            : {
    8093                 :            :         const struct mlx5_flow_driver_ops *fops;
    8094                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
    8095                 :            :         enum mlx5_flow_drv_type drv_type = flow_get_drv_type(dev, &attr);
    8096                 :            : 
    8097                 :          0 :         fops = flow_get_drv_ops(drv_type);
    8098                 :          0 :         fops->list_destroy(dev, type, flow_idx);
    8099                 :          0 : }
    8100                 :            : 
    8101                 :            : /**
    8102                 :            :  * Destroy all flows.
    8103                 :            :  *
    8104                 :            :  * @param dev
    8105                 :            :  *   Pointer to Ethernet device.
    8106                 :            :  * @param type
    8107                 :            :  *   Flow type to be flushed.
    8108                 :            :  * @param active
    8109                 :            :  *   If flushing is called actively.
    8110                 :            :  */
    8111                 :            : void
    8112                 :          0 : mlx5_flow_list_flush(struct rte_eth_dev *dev, enum mlx5_flow_type type,
    8113                 :            :                      bool active)
    8114                 :            : {
    8115                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8116                 :          0 :         uint32_t num_flushed = 0, fidx = 1;
    8117                 :            :         struct rte_flow *flow;
    8118                 :            :         struct rte_pmd_mlx5_flow_engine_mode_info *mode_info = &priv->mode_info;
    8119                 :            :         struct mlx5_dv_flow_info *flow_info;
    8120                 :            : 
    8121                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
    8122   [ #  #  #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2 &&
    8123                 :            :             type == MLX5_FLOW_TYPE_GEN) {
    8124                 :          0 :                 priv->hws_rule_flushing = true;
    8125                 :          0 :                 flow_hw_q_flow_flush(dev, NULL);
    8126                 :          0 :                 priv->hws_rule_flushing = false;
    8127                 :            :         }
    8128                 :            : #endif
    8129         [ #  # ]:          0 :         MLX5_IPOOL_FOREACH(priv->flows[type], fidx, flow) {
    8130         [ #  # ]:          0 :                 if (priv->sh->config.dv_flow_en == 2) {
    8131                 :          0 :                         mlx5_flow_list_destroy(dev, type, (uintptr_t)flow);
    8132                 :            :                 } else {
    8133                 :          0 :                         mlx5_flow_list_destroy(dev, type, fidx);
    8134                 :            :                 }
    8135   [ #  #  #  # ]:          0 :                 if (unlikely(mlx5_need_cache_flow(priv, NULL) && type == MLX5_FLOW_TYPE_GEN)) {
    8136                 :          0 :                         flow_info = LIST_FIRST(&mode_info->hot_upgrade);
    8137         [ #  # ]:          0 :                         while (flow_info) {
    8138                 :            :                                 /* Romove the cache flow info. */
    8139         [ #  # ]:          0 :                                 if (flow_info->flow_idx_low_prio == (uint32_t)(uintptr_t)fidx) {
    8140                 :            :                                         MLX5_ASSERT(!flow_info->flow_idx_high_prio);
    8141         [ #  # ]:          0 :                                         LIST_REMOVE(flow_info, next);
    8142                 :          0 :                                         mlx5_free(flow_info->items);
    8143                 :          0 :                                         mlx5_free(flow_info->actions);
    8144                 :          0 :                                         mlx5_free(flow_info);
    8145                 :          0 :                                         break;
    8146                 :            :                                 }
    8147                 :          0 :                                 flow_info = LIST_NEXT(flow_info, next);
    8148                 :            :                         }
    8149                 :            :                 }
    8150                 :          0 :                 num_flushed++;
    8151                 :            :         }
    8152         [ #  # ]:          0 :         if (active) {
    8153                 :          0 :                 DRV_LOG(INFO, "port %u: %u flows flushed before stopping",
    8154                 :            :                         dev->data->port_id, num_flushed);
    8155                 :            :         }
    8156                 :          0 : }
    8157                 :            : 
    8158                 :            : /**
    8159                 :            :  * Stop all default actions for flows.
    8160                 :            :  *
    8161                 :            :  * @param dev
    8162                 :            :  *   Pointer to Ethernet device.
    8163                 :            :  */
    8164                 :            : void
    8165                 :          0 : mlx5_flow_stop_default(struct rte_eth_dev *dev)
    8166                 :            : {
    8167                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    8168                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8169                 :            : 
    8170         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2) {
    8171                 :          0 :                 mlx5_flow_nta_del_default_copy_action(dev);
    8172         [ #  # ]:          0 :                 if (!rte_atomic_load_explicit(&priv->hws_mark_refcnt,
    8173                 :            :                                               rte_memory_order_relaxed))
    8174                 :          0 :                         flow_hw_rxq_flag_set(dev, false);
    8175                 :          0 :                 return;
    8176                 :            :         }
    8177                 :            : #endif
    8178                 :          0 :         flow_mreg_del_default_copy_action(dev);
    8179                 :          0 :         flow_rxq_flags_clear(dev);
    8180                 :            : }
    8181                 :            : 
    8182                 :            : /**
    8183                 :            :  * Set rxq flag.
    8184                 :            :  *
    8185                 :            :  * @param[in] dev
    8186                 :            :  *   Pointer to the rte_eth_dev structure.
    8187                 :            :  * @param[in] enable
    8188                 :            :  *   Flag to enable or not.
    8189                 :            :  */
    8190                 :            : void
    8191                 :          0 : flow_hw_rxq_flag_set(struct rte_eth_dev *dev, bool enable)
    8192                 :            : {
    8193                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8194                 :            :         unsigned int i;
    8195                 :            : 
    8196   [ #  #  #  #  :          0 :         if ((!priv->mark_enabled && !enable) ||
                   #  # ]
    8197         [ #  # ]:          0 :             (priv->mark_enabled && enable))
    8198                 :            :                 return;
    8199         [ #  # ]:          0 :         for (i = 0; i < priv->rxqs_n; ++i) {
    8200                 :          0 :                 struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
    8201                 :            : 
    8202                 :            :                 /* With RXQ start/stop feature, RXQ might be stopped. */
    8203         [ #  # ]:          0 :                 if (!rxq_ctrl)
    8204                 :          0 :                         continue;
    8205                 :          0 :                 rxq_ctrl->rxq.mark = enable;
    8206                 :            :         }
    8207                 :          0 :         priv->mark_enabled = enable;
    8208                 :            : }
    8209                 :            : 
    8210                 :            : /**
    8211                 :            :  * Start all default actions for flows.
    8212                 :            :  *
    8213                 :            :  * @param dev
    8214                 :            :  *   Pointer to Ethernet device.
    8215                 :            :  * @return
    8216                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    8217                 :            :  */
    8218                 :            : int
    8219                 :          0 : mlx5_flow_start_default(struct rte_eth_dev *dev)
    8220                 :            : {
    8221                 :            :         struct rte_flow_error error;
    8222                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    8223                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8224                 :            : 
    8225         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
    8226                 :          0 :                 return mlx5_flow_nta_add_default_copy_action(dev, &error);
    8227                 :            : #endif
    8228                 :            :         /* Make sure default copy action (reg_c[0] -> reg_b) is created. */
    8229                 :          0 :         return flow_mreg_add_default_copy_action(dev, &error);
    8230                 :            : }
    8231                 :            : 
    8232                 :            : /**
    8233                 :            :  * Release key of thread specific flow workspace data.
    8234                 :            :  */
    8235                 :            : void
    8236                 :          0 : flow_release_workspace(void *data)
    8237                 :            : {
    8238                 :            :         struct mlx5_flow_workspace *wks = data;
    8239                 :            :         struct mlx5_flow_workspace *next;
    8240                 :            : 
    8241         [ #  # ]:          0 :         while (wks) {
    8242                 :          0 :                 next = wks->next;
    8243                 :          0 :                 free(wks);
    8244                 :            :                 wks = next;
    8245                 :            :         }
    8246                 :          0 : }
    8247                 :            : 
    8248                 :            : /**
    8249                 :            :  * Get thread specific current flow workspace.
    8250                 :            :  *
    8251                 :            :  * @return pointer to thread specific flow workspace data, NULL on error.
    8252                 :            :  */
    8253                 :            : struct mlx5_flow_workspace*
    8254                 :          0 : mlx5_flow_get_thread_workspace(void)
    8255                 :            : {
    8256                 :            :         struct mlx5_flow_workspace *data;
    8257                 :            : 
    8258                 :          0 :         data = mlx5_flow_os_get_specific_workspace();
    8259                 :            :         MLX5_ASSERT(data && data->inuse);
    8260   [ #  #  #  # ]:          0 :         if (!data || !data->inuse)
    8261                 :          0 :                 DRV_LOG(ERR, "flow workspace not initialized.");
    8262                 :          0 :         return data;
    8263                 :            : }
    8264                 :            : 
    8265                 :            : /**
    8266                 :            :  * Allocate and init new flow workspace.
    8267                 :            :  *
    8268                 :            :  * @return pointer to flow workspace data, NULL on error.
    8269                 :            :  */
    8270                 :            : static struct mlx5_flow_workspace*
    8271                 :          0 : flow_alloc_thread_workspace(void)
    8272                 :            : {
    8273                 :            :         size_t data_size = RTE_ALIGN(sizeof(struct mlx5_flow_workspace), sizeof(long));
    8274                 :            :         size_t rss_queue_array_size = sizeof(uint16_t) * RTE_ETH_RSS_RETA_SIZE_512;
    8275                 :            :         size_t alloc_size = data_size + rss_queue_array_size;
    8276                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    8277                 :            :         /* Dummy table size for the non-template API. */
    8278                 :            :         alloc_size += sizeof(struct rte_flow_template_table);
    8279                 :            : #endif
    8280                 :          0 :         struct mlx5_flow_workspace *data = calloc(1, alloc_size);
    8281                 :            : 
    8282         [ #  # ]:          0 :         if (!data) {
    8283                 :          0 :                 DRV_LOG(ERR, "Failed to allocate flow workspace memory.");
    8284                 :          0 :                 return NULL;
    8285                 :            :         }
    8286                 :          0 :         data->rss_desc.queue = RTE_PTR_ADD(data, data_size);
    8287                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    8288                 :          0 :         data->table = RTE_PTR_ADD(data->rss_desc.queue, rss_queue_array_size);
    8289                 :            : #endif
    8290                 :          0 :         return data;
    8291                 :            : }
    8292                 :            : 
    8293                 :            : /**
    8294                 :            :  * Get new thread specific flow workspace.
    8295                 :            :  *
    8296                 :            :  * If current workspace inuse, create new one and set as current.
    8297                 :            :  *
    8298                 :            :  * @return pointer to thread specific flow workspace data, NULL on error.
    8299                 :            :  */
    8300                 :            : struct mlx5_flow_workspace*
    8301                 :          0 : mlx5_flow_push_thread_workspace(void)
    8302                 :            : {
    8303                 :            :         struct mlx5_flow_workspace *curr;
    8304                 :            :         struct mlx5_flow_workspace *data;
    8305                 :            : 
    8306                 :          0 :         curr = mlx5_flow_os_get_specific_workspace();
    8307         [ #  # ]:          0 :         if (!curr) {
    8308                 :          0 :                 data = flow_alloc_thread_workspace();
    8309         [ #  # ]:          0 :                 if (!data)
    8310                 :            :                         return NULL;
    8311                 :          0 :                 mlx5_flow_os_workspace_gc_add(data);
    8312         [ #  # ]:          0 :         } else if (!curr->inuse) {
    8313                 :            :                 data = curr;
    8314         [ #  # ]:          0 :         } else if (curr->next) {
    8315                 :            :                 data = curr->next;
    8316                 :            :         } else {
    8317                 :          0 :                 data = flow_alloc_thread_workspace();
    8318         [ #  # ]:          0 :                 if (!data)
    8319                 :            :                         return NULL;
    8320                 :          0 :                 curr->next = data;
    8321                 :          0 :                 data->prev = curr;
    8322                 :            :         }
    8323                 :          0 :         data->inuse = 1;
    8324                 :          0 :         data->flow_idx = 0;
    8325                 :            :         /* Set as current workspace */
    8326         [ #  # ]:          0 :         if (mlx5_flow_os_set_specific_workspace(data))
    8327                 :          0 :                 DRV_LOG(ERR, "Failed to set flow workspace to thread.");
    8328                 :            :         return data;
    8329                 :            : }
    8330                 :            : 
    8331                 :            : /**
    8332                 :            :  * Close current thread specific flow workspace.
    8333                 :            :  *
    8334                 :            :  * If previous workspace available, set it as current.
    8335                 :            :  *
    8336                 :            :  * @return pointer to thread specific flow workspace data, NULL on error.
    8337                 :            :  */
    8338                 :            : void
    8339                 :          0 : mlx5_flow_pop_thread_workspace(void)
    8340                 :            : {
    8341                 :          0 :         struct mlx5_flow_workspace *data = mlx5_flow_get_thread_workspace();
    8342                 :            : 
    8343         [ #  # ]:          0 :         if (!data)
    8344                 :            :                 return;
    8345         [ #  # ]:          0 :         if (!data->inuse) {
    8346                 :          0 :                 DRV_LOG(ERR, "Failed to close unused flow workspace.");
    8347                 :          0 :                 return;
    8348                 :            :         }
    8349                 :          0 :         data->inuse = 0;
    8350         [ #  # ]:          0 :         if (!data->prev)
    8351                 :            :                 return;
    8352         [ #  # ]:          0 :         if (mlx5_flow_os_set_specific_workspace(data->prev))
    8353                 :          0 :                 DRV_LOG(ERR, "Failed to set flow workspace to thread.");
    8354                 :            : }
    8355                 :            : 
    8356                 :            : /**
    8357                 :            :  * Verify the flow list is empty
    8358                 :            :  *
    8359                 :            :  * @param dev
    8360                 :            :  *  Pointer to Ethernet device.
    8361                 :            :  *
    8362                 :            :  * @return the number of flows not released.
    8363                 :            :  */
    8364                 :            : int
    8365                 :          0 : mlx5_flow_verify(struct rte_eth_dev *dev __rte_unused)
    8366                 :            : {
    8367                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8368                 :            :         struct rte_flow *flow;
    8369                 :            :         uint32_t idx = 0;
    8370                 :            :         int ret = 0, i;
    8371                 :            : 
    8372         [ #  # ]:          0 :         for (i = 0; i < MLX5_FLOW_TYPE_MAXI; i++) {
    8373         [ #  # ]:          0 :                 MLX5_IPOOL_FOREACH(priv->flows[i], idx, flow) {
    8374                 :          0 :                         DRV_LOG(DEBUG, "port %u flow %p still referenced",
    8375                 :            :                                 dev->data->port_id, (void *)flow);
    8376                 :          0 :                         ret++;
    8377                 :            :                 }
    8378                 :            :         }
    8379                 :          0 :         return ret;
    8380                 :            : }
    8381                 :            : 
    8382                 :            : /**
    8383                 :            :  * Enable default hairpin egress flow.
    8384                 :            :  *
    8385                 :            :  * @param dev
    8386                 :            :  *   Pointer to Ethernet device.
    8387                 :            :  * @param sq_num
    8388                 :            :  *   The SQ hw number.
    8389                 :            :  *
    8390                 :            :  * @return
    8391                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    8392                 :            :  */
    8393                 :            : int
    8394                 :          0 : mlx5_ctrl_flow_source_queue(struct rte_eth_dev *dev,
    8395                 :            :                             uint32_t sq_num)
    8396                 :            : {
    8397                 :          0 :         const struct rte_flow_attr attr = {
    8398                 :            :                 .egress = 1,
    8399                 :            :                 .priority = 0,
    8400                 :            :         };
    8401                 :          0 :         struct mlx5_rte_flow_item_sq queue_spec = {
    8402                 :            :                 .queue = sq_num,
    8403                 :            :         };
    8404                 :          0 :         struct mlx5_rte_flow_item_sq queue_mask = {
    8405                 :            :                 .queue = UINT32_MAX,
    8406                 :            :         };
    8407                 :          0 :         struct rte_flow_item items[] = {
    8408                 :            :                 {
    8409                 :            :                         .type = (enum rte_flow_item_type)
    8410                 :            :                                 MLX5_RTE_FLOW_ITEM_TYPE_SQ,
    8411                 :            :                         .spec = &queue_spec,
    8412                 :            :                         .last = NULL,
    8413                 :            :                         .mask = &queue_mask,
    8414                 :            :                 },
    8415                 :            :                 {
    8416                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    8417                 :            :                 },
    8418                 :            :         };
    8419                 :          0 :         struct rte_flow_action_jump jump = {
    8420                 :            :                 .group = MLX5_HAIRPIN_TX_TABLE,
    8421                 :            :         };
    8422                 :            :         struct rte_flow_action actions[2];
    8423                 :            :         uint32_t flow_idx;
    8424                 :            :         struct rte_flow_error error;
    8425                 :            : 
    8426                 :          0 :         actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP;
    8427                 :          0 :         actions[0].conf = &jump;
    8428                 :          0 :         actions[1].type = RTE_FLOW_ACTION_TYPE_END;
    8429                 :          0 :         flow_idx = mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_CTL,
    8430                 :            :                                     &attr, items, actions, false, &error);
    8431         [ #  # ]:          0 :         if (!flow_idx) {
    8432         [ #  # ]:          0 :                 DRV_LOG(DEBUG,
    8433                 :            :                         "Failed to create ctrl flow: rte_errno(%d),"
    8434                 :            :                         " type(%d), message(%s)",
    8435                 :            :                         rte_errno, error.type,
    8436                 :            :                         error.message ? error.message : " (no stated reason)");
    8437                 :          0 :                 return -rte_errno;
    8438                 :            :         }
    8439                 :            :         return 0;
    8440                 :            : }
    8441                 :            : 
    8442                 :            : /**
    8443                 :            :  * Enable a control flow configured from the control plane.
    8444                 :            :  *
    8445                 :            :  * @param dev
    8446                 :            :  *   Pointer to Ethernet device.
    8447                 :            :  * @param eth_spec
    8448                 :            :  *   An Ethernet flow spec to apply.
    8449                 :            :  * @param eth_mask
    8450                 :            :  *   An Ethernet flow mask to apply.
    8451                 :            :  * @param vlan_spec
    8452                 :            :  *   A VLAN flow spec to apply.
    8453                 :            :  * @param vlan_mask
    8454                 :            :  *   A VLAN flow mask to apply.
    8455                 :            :  *
    8456                 :            :  * @return
    8457                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    8458                 :            :  */
    8459                 :            : int
    8460                 :          0 : mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev,
    8461                 :            :                     struct rte_flow_item_eth *eth_spec,
    8462                 :            :                     struct rte_flow_item_eth *eth_mask,
    8463                 :            :                     struct rte_flow_item_vlan *vlan_spec,
    8464                 :            :                     struct rte_flow_item_vlan *vlan_mask)
    8465                 :            : {
    8466                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8467                 :          0 :         const struct rte_flow_attr attr = {
    8468                 :            :                 .ingress = 1,
    8469                 :            :                 .priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR,
    8470                 :            :         };
    8471                 :          0 :         struct rte_flow_item items[] = {
    8472                 :            :                 {
    8473                 :            :                         .type = RTE_FLOW_ITEM_TYPE_ETH,
    8474                 :            :                         .spec = eth_spec,
    8475                 :            :                         .last = NULL,
    8476                 :            :                         .mask = eth_mask,
    8477                 :            :                 },
    8478                 :            :                 {
    8479         [ #  # ]:          0 :                         .type = (vlan_spec) ? RTE_FLOW_ITEM_TYPE_VLAN :
    8480                 :            :                                               RTE_FLOW_ITEM_TYPE_END,
    8481                 :            :                         .spec = vlan_spec,
    8482                 :            :                         .last = NULL,
    8483                 :            :                         .mask = vlan_mask,
    8484                 :            :                 },
    8485                 :            :                 {
    8486                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    8487                 :            :                 },
    8488                 :            :         };
    8489                 :          0 :         uint16_t *queue = alloca(sizeof(uint16_t) * priv->reta_idx_n);
    8490                 :          0 :         struct rte_flow_action_rss action_rss = {
    8491                 :            :                 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
    8492                 :            :                 .level = 0,
    8493                 :          0 :                 .types = priv->rss_conf.rss_hf,
    8494                 :          0 :                 .key_len = priv->rss_conf.rss_key_len,
    8495                 :            :                 .queue_num = priv->reta_idx_n,
    8496                 :          0 :                 .key = priv->rss_conf.rss_key,
    8497                 :            :                 .queue = queue,
    8498                 :            :         };
    8499                 :          0 :         struct rte_flow_action actions[] = {
    8500                 :            :                 {
    8501                 :            :                         .type = RTE_FLOW_ACTION_TYPE_RSS,
    8502                 :            :                         .conf = &action_rss,
    8503                 :            :                 },
    8504                 :            :                 {
    8505                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
    8506                 :            :                 },
    8507                 :            :         };
    8508                 :            :         uintptr_t flow_idx;
    8509                 :            :         struct rte_flow_error error;
    8510                 :            :         struct mlx5_ctrl_flow_entry *entry;
    8511                 :            :         unsigned int i;
    8512                 :            : 
    8513   [ #  #  #  # ]:          0 :         if (!priv->reta_idx_n || !priv->rxqs_n) {
    8514                 :            :                 return 0;
    8515                 :            :         }
    8516         [ #  # ]:          0 :         if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG))
    8517                 :          0 :                 action_rss.types = 0;
    8518         [ #  # ]:          0 :         for (i = 0; i != priv->reta_idx_n; ++i)
    8519                 :          0 :                 queue[i] = (*priv->reta_idx)[i];
    8520                 :            : 
    8521                 :          0 :         entry = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*entry), alignof(typeof(*entry)), SOCKET_ID_ANY);
    8522         [ #  # ]:          0 :         if (entry == NULL) {
    8523                 :          0 :                 rte_errno = ENOMEM;
    8524                 :          0 :                 goto err;
    8525                 :            :         }
    8526                 :            : 
    8527                 :          0 :         entry->owner_dev = dev;
    8528         [ #  # ]:          0 :         if (vlan_spec == NULL) {
    8529                 :          0 :                 entry->info.type = MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC;
    8530                 :            :         } else {
    8531                 :          0 :                 entry->info.type = MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC_VLAN;
    8532         [ #  # ]:          0 :                 entry->info.uc.vlan = rte_be_to_cpu_16(vlan_spec->hdr.vlan_tci);
    8533                 :            :         }
    8534                 :          0 :         entry->info.uc.dmac = eth_spec->hdr.dst_addr;
    8535                 :            : 
    8536                 :          0 :         flow_idx = mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_CTL,
    8537                 :            :                                     &attr, items, actions, false, &error);
    8538         [ #  # ]:          0 :         if (!flow_idx) {
    8539                 :          0 :                 mlx5_free(entry);
    8540                 :          0 :                 goto err;
    8541                 :            :         }
    8542                 :            : 
    8543                 :          0 :         entry->flow = (struct rte_flow *)flow_idx;
    8544         [ #  # ]:          0 :         LIST_INSERT_HEAD(&priv->hw_ctrl_flows, entry, next);
    8545                 :            : 
    8546                 :          0 :         return 0;
    8547                 :            : 
    8548                 :          0 : err:
    8549                 :          0 :         return -rte_errno;
    8550                 :            : }
    8551                 :            : 
    8552                 :            : /**
    8553                 :            :  * Enable a flow control configured from the control plane.
    8554                 :            :  *
    8555                 :            :  * @param dev
    8556                 :            :  *   Pointer to Ethernet device.
    8557                 :            :  * @param eth_spec
    8558                 :            :  *   An Ethernet flow spec to apply.
    8559                 :            :  * @param eth_mask
    8560                 :            :  *   An Ethernet flow mask to apply.
    8561                 :            :  *
    8562                 :            :  * @return
    8563                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    8564                 :            :  */
    8565                 :            : int
    8566                 :          0 : mlx5_ctrl_flow(struct rte_eth_dev *dev,
    8567                 :            :                struct rte_flow_item_eth *eth_spec,
    8568                 :            :                struct rte_flow_item_eth *eth_mask)
    8569                 :            : {
    8570                 :          0 :         return mlx5_ctrl_flow_vlan(dev, eth_spec, eth_mask, NULL, NULL);
    8571                 :            : }
    8572                 :            : 
    8573                 :            : int
    8574                 :          0 : mlx5_legacy_dmac_flow_create(struct rte_eth_dev *dev, const struct rte_ether_addr *addr)
    8575                 :            : {
    8576                 :          0 :         struct rte_flow_item_eth unicast = {
    8577                 :            :                 .hdr.dst_addr = *addr,
    8578                 :            :         };
    8579                 :          0 :         struct rte_flow_item_eth unicast_mask = {
    8580                 :            :                 .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    8581                 :            :         };
    8582                 :            : 
    8583                 :          0 :         return mlx5_ctrl_flow(dev, &unicast, &unicast_mask);
    8584                 :            : }
    8585                 :            : 
    8586                 :            : int
    8587                 :          0 : mlx5_legacy_dmac_vlan_flow_create(struct rte_eth_dev *dev,
    8588                 :            :                                   const struct rte_ether_addr *addr,
    8589                 :            :                                   const uint16_t vid)
    8590                 :            : {
    8591                 :          0 :         struct rte_flow_item_eth unicast_spec = {
    8592                 :            :                 .hdr.dst_addr = *addr,
    8593                 :            :         };
    8594                 :          0 :         struct rte_flow_item_eth unicast_mask = {
    8595                 :            :                 .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    8596                 :            :         };
    8597                 :          0 :         struct rte_flow_item_vlan vlan_spec = {
    8598         [ #  # ]:          0 :                 .hdr.vlan_tci = rte_cpu_to_be_16(vid),
    8599                 :            :         };
    8600                 :          0 :         struct rte_flow_item_vlan vlan_mask = rte_flow_item_vlan_mask;
    8601                 :            : 
    8602                 :          0 :         return mlx5_ctrl_flow_vlan(dev, &unicast_spec, &unicast_mask, &vlan_spec, &vlan_mask);
    8603                 :            : }
    8604                 :            : 
    8605                 :            : void
    8606                 :          0 : mlx5_legacy_ctrl_flow_destroy(struct rte_eth_dev *dev, struct mlx5_ctrl_flow_entry *entry)
    8607                 :            : {
    8608                 :            :         uintptr_t flow_idx;
    8609                 :            : 
    8610                 :          0 :         flow_idx = (uintptr_t)entry->flow;
    8611                 :          0 :         mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_CTL, flow_idx);
    8612         [ #  # ]:          0 :         LIST_REMOVE(entry, next);
    8613                 :          0 :         mlx5_free(entry);
    8614                 :          0 : }
    8615                 :            : 
    8616                 :            : int
    8617                 :          0 : mlx5_legacy_dmac_flow_destroy(struct rte_eth_dev *dev, const struct rte_ether_addr *addr)
    8618                 :            : {
    8619                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8620                 :            :         struct mlx5_ctrl_flow_entry *entry;
    8621                 :            : 
    8622         [ #  # ]:          0 :         LIST_FOREACH(entry, &priv->hw_ctrl_flows, next) {
    8623   [ #  #  #  # ]:          0 :                 if (entry->info.type != MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC ||
    8624                 :            :                     !rte_is_same_ether_addr(addr, &entry->info.uc.dmac))
    8625                 :            :                         continue;
    8626                 :            : 
    8627                 :          0 :                 mlx5_legacy_ctrl_flow_destroy(dev, entry);
    8628                 :          0 :                 return 0;
    8629                 :            :         }
    8630                 :            :         return 0;
    8631                 :            : }
    8632                 :            : 
    8633                 :            : int
    8634                 :          0 : mlx5_legacy_dmac_vlan_flow_destroy(struct rte_eth_dev *dev,
    8635                 :            :                                    const struct rte_ether_addr *addr,
    8636                 :            :                                    const uint16_t vid)
    8637                 :            : {
    8638                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8639                 :            :         struct mlx5_ctrl_flow_entry *entry;
    8640                 :            : 
    8641         [ #  # ]:          0 :         LIST_FOREACH(entry, &priv->hw_ctrl_flows, next) {
    8642   [ #  #  #  # ]:          0 :                 if (entry->info.type != MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC_VLAN ||
    8643                 :          0 :                     !rte_is_same_ether_addr(addr, &entry->info.uc.dmac) ||
    8644         [ #  # ]:          0 :                     vid != entry->info.uc.vlan)
    8645                 :            :                         continue;
    8646                 :            : 
    8647                 :          0 :                 mlx5_legacy_ctrl_flow_destroy(dev, entry);
    8648                 :          0 :                 return 0;
    8649                 :            :         }
    8650                 :            :         return 0;
    8651                 :            : }
    8652                 :            : 
    8653                 :            : /**
    8654                 :            :  * Create default miss flow rule matching lacp traffic
    8655                 :            :  *
    8656                 :            :  * @param dev
    8657                 :            :  *   Pointer to Ethernet device.
    8658                 :            :  * @param eth_spec
    8659                 :            :  *   An Ethernet flow spec to apply.
    8660                 :            :  *
    8661                 :            :  * @return
    8662                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    8663                 :            :  */
    8664                 :            : int
    8665                 :          0 : mlx5_flow_lacp_miss(struct rte_eth_dev *dev)
    8666                 :            : {
    8667                 :            :         /*
    8668                 :            :          * The LACP matching is done by only using ether type since using
    8669                 :            :          * a multicast dst mac causes kernel to give low priority to this flow.
    8670                 :            :          */
    8671                 :            :         static const struct rte_flow_item_eth lacp_spec = {
    8672                 :            :                 .hdr.ether_type = RTE_BE16(0x8809),
    8673                 :            :         };
    8674                 :            :         static const struct rte_flow_item_eth lacp_mask = {
    8675                 :            :                 .hdr.ether_type = 0xffff,
    8676                 :            :         };
    8677                 :          0 :         const struct rte_flow_attr attr = {
    8678                 :            :                 .ingress = 1,
    8679                 :            :         };
    8680                 :          0 :         struct rte_flow_item items[] = {
    8681                 :            :                 {
    8682                 :            :                         .type = RTE_FLOW_ITEM_TYPE_ETH,
    8683                 :            :                         .spec = &lacp_spec,
    8684                 :            :                         .mask = &lacp_mask,
    8685                 :            :                 },
    8686                 :            :                 {
    8687                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
    8688                 :            :                 },
    8689                 :            :         };
    8690                 :          0 :         struct rte_flow_action actions[] = {
    8691                 :            :                 {
    8692                 :            :                         .type = (enum rte_flow_action_type)
    8693                 :            :                                 MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS,
    8694                 :            :                 },
    8695                 :            :                 {
    8696                 :            :                         .type = RTE_FLOW_ACTION_TYPE_END,
    8697                 :            :                 },
    8698                 :            :         };
    8699                 :            :         struct rte_flow_error error;
    8700                 :          0 :         uint32_t flow_idx = mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_CTL,
    8701                 :            :                                         &attr, items, actions,
    8702                 :            :                                         false, &error);
    8703                 :            : 
    8704         [ #  # ]:          0 :         if (!flow_idx)
    8705                 :          0 :                 return -rte_errno;
    8706                 :            :         return 0;
    8707                 :            : }
    8708                 :            : 
    8709                 :            : /**
    8710                 :            :  * Destroy a flow.
    8711                 :            :  *
    8712                 :            :  * @see rte_flow_destroy()
    8713                 :            :  * @see rte_flow_ops
    8714                 :            :  */
    8715                 :            : int
    8716                 :          0 : mlx5_flow_destroy(struct rte_eth_dev *dev,
    8717                 :            :                   struct rte_flow *flow,
    8718                 :            :                   struct rte_flow_error *error __rte_unused)
    8719                 :            : {
    8720                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8721                 :            :         struct rte_pmd_mlx5_flow_engine_mode_info *mode_info = &priv->mode_info;
    8722                 :            :         struct mlx5_dv_flow_info *flow_info;
    8723                 :            : 
    8724                 :          0 :         mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN,
    8725                 :            :                                 (uintptr_t)(void *)flow);
    8726         [ #  # ]:          0 :         if (unlikely(mlx5_need_cache_flow(priv, NULL))) {
    8727                 :          0 :                 flow_info = LIST_FIRST(&mode_info->hot_upgrade);
    8728         [ #  # ]:          0 :                 while (flow_info) {
    8729                 :            :                         /* Romove the cache flow info. */
    8730         [ #  # ]:          0 :                         if (flow_info->flow_idx_low_prio == (uint32_t)(uintptr_t)flow) {
    8731                 :            :                                 MLX5_ASSERT(!flow_info->flow_idx_high_prio);
    8732         [ #  # ]:          0 :                                 LIST_REMOVE(flow_info, next);
    8733                 :          0 :                                 mlx5_free(flow_info->items);
    8734                 :          0 :                                 mlx5_free(flow_info->actions);
    8735                 :          0 :                                 mlx5_free(flow_info);
    8736                 :          0 :                                 break;
    8737                 :            :                         }
    8738                 :          0 :                         flow_info = LIST_NEXT(flow_info, next);
    8739                 :            :                 }
    8740                 :            :         }
    8741                 :          0 :         return 0;
    8742                 :            : }
    8743                 :            : 
    8744                 :            : /**
    8745                 :            :  * Destroy all flows.
    8746                 :            :  *
    8747                 :            :  * @see rte_flow_flush()
    8748                 :            :  * @see rte_flow_ops
    8749                 :            :  */
    8750                 :            : int
    8751                 :          0 : mlx5_flow_flush(struct rte_eth_dev *dev,
    8752                 :            :                 struct rte_flow_error *error __rte_unused)
    8753                 :            : {
    8754                 :          0 :         mlx5_flow_list_flush(dev, MLX5_FLOW_TYPE_GEN, false);
    8755                 :          0 :         return 0;
    8756                 :            : }
    8757                 :            : 
    8758                 :            : /**
    8759                 :            :  * Isolated mode.
    8760                 :            :  *
    8761                 :            :  * @see rte_flow_isolate()
    8762                 :            :  * @see rte_flow_ops
    8763                 :            :  */
    8764                 :            : int
    8765                 :          0 : mlx5_flow_isolate(struct rte_eth_dev *dev,
    8766                 :            :                   int enable,
    8767                 :            :                   struct rte_flow_error *error)
    8768                 :            : {
    8769                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8770                 :            : 
    8771         [ #  # ]:          0 :         if (dev->data->dev_started) {
    8772                 :          0 :                 rte_flow_error_set(error, EBUSY,
    8773                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8774                 :            :                                    NULL,
    8775                 :            :                                    "port must be stopped first");
    8776                 :          0 :                 return -rte_errno;
    8777                 :            :         }
    8778   [ #  #  #  # ]:          0 :         if (!enable && !priv->sh->config.repr_matching)
    8779                 :          0 :                 return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    8780                 :            :                                           "isolated mode cannot be disabled when "
    8781                 :            :                                           "representor matching is disabled");
    8782                 :          0 :         priv->isolated = !!enable;
    8783         [ #  # ]:          0 :         if (enable)
    8784                 :          0 :                 dev->dev_ops = &mlx5_dev_ops_isolate;
    8785                 :            :         else
    8786                 :          0 :                 dev->dev_ops = &mlx5_dev_ops;
    8787                 :            : 
    8788                 :          0 :         dev->rx_descriptor_status = mlx5_rx_descriptor_status;
    8789                 :          0 :         dev->tx_descriptor_status = mlx5_tx_descriptor_status;
    8790                 :            : 
    8791                 :          0 :         return 0;
    8792                 :            : }
    8793                 :            : 
    8794                 :            : /**
    8795                 :            :  * Query a flow.
    8796                 :            :  *
    8797                 :            :  * @see rte_flow_query()
    8798                 :            :  * @see rte_flow_ops
    8799                 :            :  */
    8800                 :            : static int
    8801                 :          0 : flow_drv_query(struct rte_eth_dev *dev,
    8802                 :            :                struct rte_flow *eflow,
    8803                 :            :                const struct rte_flow_action *actions,
    8804                 :            :                void *data,
    8805                 :            :                struct rte_flow_error *error)
    8806                 :            : {
    8807                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    8808                 :            :         const struct mlx5_flow_driver_ops *fops;
    8809                 :            :         struct rte_flow *flow = NULL;
    8810                 :            :         enum mlx5_flow_drv_type ftype = MLX5_FLOW_TYPE_MIN;
    8811                 :            : 
    8812         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2) {
    8813                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    8814                 :            :                 flow = eflow;
    8815                 :            :                 ftype = MLX5_FLOW_TYPE_HW;
    8816                 :            : #endif
    8817                 :            :         } else {
    8818                 :          0 :                 flow = (struct rte_flow *)mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN],
    8819                 :            :                                 (uintptr_t)(void *)eflow);
    8820                 :            :         }
    8821         [ #  # ]:          0 :         if (!flow) {
    8822                 :          0 :                 return rte_flow_error_set(error, ENOENT,
    8823                 :            :                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8824                 :            :                           NULL,
    8825                 :            :                           "invalid flow handle");
    8826                 :            :         }
    8827         [ #  # ]:          0 :         if (ftype == MLX5_FLOW_TYPE_MIN)
    8828                 :          0 :                 ftype = flow->drv_type;
    8829                 :            :         MLX5_ASSERT(ftype > MLX5_FLOW_TYPE_MIN && ftype < MLX5_FLOW_TYPE_MAX);
    8830                 :          0 :         fops = flow_get_drv_ops(ftype);
    8831                 :            : 
    8832                 :          0 :         return fops->query(dev, flow, actions, data, error);
    8833                 :            : }
    8834                 :            : 
    8835                 :            : /**
    8836                 :            :  * Query a flow.
    8837                 :            :  *
    8838                 :            :  * @see rte_flow_query()
    8839                 :            :  * @see rte_flow_ops
    8840                 :            :  */
    8841                 :            : int
    8842                 :          0 : mlx5_flow_query(struct rte_eth_dev *dev,
    8843                 :            :                 struct rte_flow *flow,
    8844                 :            :                 const struct rte_flow_action *actions,
    8845                 :            :                 void *data,
    8846                 :            :                 struct rte_flow_error *error)
    8847                 :            : {
    8848                 :            :         int ret;
    8849                 :            : 
    8850                 :          0 :         ret = flow_drv_query(dev, flow, actions, data,
    8851                 :            :                              error);
    8852                 :            :         if (ret < 0)
    8853                 :            :                 return ret;
    8854                 :            :         return 0;
    8855                 :            : }
    8856                 :            : 
    8857                 :            : /**
    8858                 :            :  * Get rte_flow callbacks.
    8859                 :            :  *
    8860                 :            :  * @param dev
    8861                 :            :  *   Pointer to Ethernet device structure.
    8862                 :            :  * @param ops
    8863                 :            :  *   Pointer to operation-specific structure.
    8864                 :            :  *
    8865                 :            :  * @return 0
    8866                 :            :  */
    8867                 :            : int
    8868                 :          0 : mlx5_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
    8869                 :            :                   const struct rte_flow_ops **ops)
    8870                 :            : {
    8871                 :          0 :         *ops = &mlx5_flow_ops;
    8872                 :          0 :         return 0;
    8873                 :            : }
    8874                 :            : 
    8875                 :            : /**
    8876                 :            :  * Validate meter policy actions.
    8877                 :            :  * Dispatcher for action type specific validation.
    8878                 :            :  *
    8879                 :            :  * @param[in] dev
    8880                 :            :  *   Pointer to the Ethernet device structure.
    8881                 :            :  * @param[in] action
    8882                 :            :  *   The meter policy action object to validate.
    8883                 :            :  * @param[in] attr
    8884                 :            :  *   Attributes of flow to determine steering domain.
    8885                 :            :  * @param[out] is_rss
    8886                 :            :  *   Is RSS or not.
    8887                 :            :  * @param[out] domain_bitmap
    8888                 :            :  *   Domain bitmap.
    8889                 :            :  * @param[out] is_def_policy
    8890                 :            :  *   Is default policy or not.
    8891                 :            :  * @param[out] error
    8892                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
    8893                 :            :  *   error only.
    8894                 :            :  *
    8895                 :            :  * @return
    8896                 :            :  *   0 on success, otherwise negative errno value.
    8897                 :            :  */
    8898                 :            : int
    8899                 :          0 : mlx5_flow_validate_mtr_acts(struct rte_eth_dev *dev,
    8900                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
    8901                 :            :                         struct rte_flow_attr *attr,
    8902                 :            :                         bool *is_rss,
    8903                 :            :                         uint8_t *domain_bitmap,
    8904                 :            :                         uint8_t *policy_mode,
    8905                 :            :                         struct rte_mtr_error *error)
    8906                 :            : {
    8907                 :            :         const struct mlx5_flow_driver_ops *fops;
    8908                 :            : 
    8909                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    8910                 :          0 :         return fops->validate_mtr_acts(dev, actions, attr, is_rss,
    8911                 :            :                                        domain_bitmap, policy_mode, error);
    8912                 :            : }
    8913                 :            : 
    8914                 :            : /**
    8915                 :            :  * Destroy the meter table set.
    8916                 :            :  *
    8917                 :            :  * @param[in] dev
    8918                 :            :  *   Pointer to Ethernet device.
    8919                 :            :  * @param[in] mtr_policy
    8920                 :            :  *   Meter policy struct.
    8921                 :            :  */
    8922                 :            : void
    8923                 :          0 : mlx5_flow_destroy_mtr_acts(struct rte_eth_dev *dev,
    8924                 :            :                       struct mlx5_flow_meter_policy *mtr_policy)
    8925                 :            : {
    8926                 :            :         const struct mlx5_flow_driver_ops *fops;
    8927                 :            : 
    8928                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    8929                 :          0 :         fops->destroy_mtr_acts(dev, mtr_policy);
    8930                 :          0 : }
    8931                 :            : 
    8932                 :            : /**
    8933                 :            :  * Create policy action, lock free,
    8934                 :            :  * (mutex should be acquired by caller).
    8935                 :            :  * Dispatcher for action type specific call.
    8936                 :            :  *
    8937                 :            :  * @param[in] dev
    8938                 :            :  *   Pointer to the Ethernet device structure.
    8939                 :            :  * @param[in] mtr_policy
    8940                 :            :  *   Meter policy struct.
    8941                 :            :  * @param[in] action
    8942                 :            :  *   Action specification used to create meter actions.
    8943                 :            :  * @param[in] attr
    8944                 :            :  *   Flow rule attributes.
    8945                 :            :  * @param[out] error
    8946                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
    8947                 :            :  *   error only.
    8948                 :            :  *
    8949                 :            :  * @return
    8950                 :            :  *   0 on success, otherwise negative errno value.
    8951                 :            :  */
    8952                 :            : int
    8953                 :          0 : mlx5_flow_create_mtr_acts(struct rte_eth_dev *dev,
    8954                 :            :                       struct mlx5_flow_meter_policy *mtr_policy,
    8955                 :            :                       const struct rte_flow_action *actions[RTE_COLORS],
    8956                 :            :                       struct rte_flow_attr *attr,
    8957                 :            :                       struct rte_mtr_error *error)
    8958                 :            : {
    8959                 :            :         const struct mlx5_flow_driver_ops *fops;
    8960                 :            : 
    8961                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    8962                 :          0 :         return fops->create_mtr_acts(dev, mtr_policy, actions, attr, error);
    8963                 :            : }
    8964                 :            : 
    8965                 :            : /**
    8966                 :            :  * Create policy rules, lock free,
    8967                 :            :  * (mutex should be acquired by caller).
    8968                 :            :  * Dispatcher for action type specific call.
    8969                 :            :  *
    8970                 :            :  * @param[in] dev
    8971                 :            :  *   Pointer to the Ethernet device structure.
    8972                 :            :  * @param[in] mtr_policy
    8973                 :            :  *   Meter policy struct.
    8974                 :            :  *
    8975                 :            :  * @return
    8976                 :            :  *   0 on success, -1 otherwise.
    8977                 :            :  */
    8978                 :            : int
    8979                 :          0 : mlx5_flow_create_policy_rules(struct rte_eth_dev *dev,
    8980                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
    8981                 :            : {
    8982                 :            :         const struct mlx5_flow_driver_ops *fops;
    8983                 :            : 
    8984                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    8985                 :          0 :         return fops->create_policy_rules(dev, mtr_policy);
    8986                 :            : }
    8987                 :            : 
    8988                 :            : /**
    8989                 :            :  * Destroy policy rules, lock free,
    8990                 :            :  * (mutex should be acquired by caller).
    8991                 :            :  * Dispatcher for action type specific call.
    8992                 :            :  *
    8993                 :            :  * @param[in] dev
    8994                 :            :  *   Pointer to the Ethernet device structure.
    8995                 :            :  * @param[in] mtr_policy
    8996                 :            :  *   Meter policy struct.
    8997                 :            :  */
    8998                 :            : void
    8999                 :          0 : mlx5_flow_destroy_policy_rules(struct rte_eth_dev *dev,
    9000                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
    9001                 :            : {
    9002                 :            :         const struct mlx5_flow_driver_ops *fops;
    9003                 :            : 
    9004                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9005                 :          0 :         fops->destroy_policy_rules(dev, mtr_policy);
    9006                 :          0 : }
    9007                 :            : 
    9008                 :            : /**
    9009                 :            :  * Destroy the default policy table set.
    9010                 :            :  *
    9011                 :            :  * @param[in] dev
    9012                 :            :  *   Pointer to Ethernet device.
    9013                 :            :  */
    9014                 :            : void
    9015                 :          0 : mlx5_flow_destroy_def_policy(struct rte_eth_dev *dev)
    9016                 :            : {
    9017                 :            :         const struct mlx5_flow_driver_ops *fops;
    9018                 :            : 
    9019                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9020                 :          0 :         fops->destroy_def_policy(dev);
    9021                 :          0 : }
    9022                 :            : 
    9023                 :            : /**
    9024                 :            :  * Destroy the default policy table set.
    9025                 :            :  *
    9026                 :            :  * @param[in] dev
    9027                 :            :  *   Pointer to Ethernet device.
    9028                 :            :  *
    9029                 :            :  * @return
    9030                 :            :  *   0 on success, -1 otherwise.
    9031                 :            :  */
    9032                 :            : int
    9033                 :          0 : mlx5_flow_create_def_policy(struct rte_eth_dev *dev)
    9034                 :            : {
    9035                 :            :         const struct mlx5_flow_driver_ops *fops;
    9036                 :            : 
    9037                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9038                 :          0 :         return fops->create_def_policy(dev);
    9039                 :            : }
    9040                 :            : 
    9041                 :            : /**
    9042                 :            :  * Create the needed meter and suffix tables.
    9043                 :            :  *
    9044                 :            :  * @param[in] dev
    9045                 :            :  *   Pointer to Ethernet device.
    9046                 :            :  *
    9047                 :            :  * @return
    9048                 :            :  *   0 on success, -1 otherwise.
    9049                 :            :  */
    9050                 :            : int
    9051                 :          0 : mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev,
    9052                 :            :                         struct mlx5_flow_meter_info *fm,
    9053                 :            :                         uint32_t mtr_idx,
    9054                 :            :                         uint8_t domain_bitmap)
    9055                 :            : {
    9056                 :            :         const struct mlx5_flow_driver_ops *fops;
    9057                 :            : 
    9058                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9059                 :          0 :         return fops->create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap);
    9060                 :            : }
    9061                 :            : 
    9062                 :            : /**
    9063                 :            :  * Destroy the meter table set.
    9064                 :            :  *
    9065                 :            :  * @param[in] dev
    9066                 :            :  *   Pointer to Ethernet device.
    9067                 :            :  * @param[in] tbl
    9068                 :            :  *   Pointer to the meter table set.
    9069                 :            :  */
    9070                 :            : void
    9071                 :          0 : mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
    9072                 :            :                            struct mlx5_flow_meter_info *fm)
    9073                 :            : {
    9074                 :            :         const struct mlx5_flow_driver_ops *fops;
    9075                 :            : 
    9076                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9077                 :          0 :         fops->destroy_mtr_tbls(dev, fm);
    9078                 :          0 : }
    9079                 :            : 
    9080                 :            : /**
    9081                 :            :  * Destroy the global meter drop table.
    9082                 :            :  *
    9083                 :            :  * @param[in] dev
    9084                 :            :  *   Pointer to Ethernet device.
    9085                 :            :  */
    9086                 :            : void
    9087                 :          0 : mlx5_flow_destroy_mtr_drop_tbls(struct rte_eth_dev *dev)
    9088                 :            : {
    9089                 :            :         const struct mlx5_flow_driver_ops *fops;
    9090                 :            : 
    9091                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9092                 :          0 :         fops->destroy_mtr_drop_tbls(dev);
    9093                 :          0 : }
    9094                 :            : 
    9095                 :            : /**
    9096                 :            :  * Destroy the sub policy table with RX queue.
    9097                 :            :  *
    9098                 :            :  * @param[in] dev
    9099                 :            :  *   Pointer to Ethernet device.
    9100                 :            :  * @param[in] mtr_policy
    9101                 :            :  *   Pointer to meter policy table.
    9102                 :            :  */
    9103                 :            : void
    9104                 :          0 : mlx5_flow_destroy_sub_policy_with_rxq(struct rte_eth_dev *dev,
    9105                 :            :                 struct mlx5_flow_meter_policy *mtr_policy)
    9106                 :            : {
    9107                 :            :         const struct mlx5_flow_driver_ops *fops;
    9108                 :            : 
    9109                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9110                 :          0 :         fops->destroy_sub_policy_with_rxq(dev, mtr_policy);
    9111                 :          0 : }
    9112                 :            : 
    9113                 :            : /**
    9114                 :            :  * Allocate the needed aso flow meter id.
    9115                 :            :  *
    9116                 :            :  * @param[in] dev
    9117                 :            :  *   Pointer to Ethernet device.
    9118                 :            :  *
    9119                 :            :  * @return
    9120                 :            :  *   Index to aso flow meter on success, NULL otherwise.
    9121                 :            :  */
    9122                 :            : uint32_t
    9123                 :          0 : mlx5_flow_mtr_alloc(struct rte_eth_dev *dev)
    9124                 :            : {
    9125                 :            :         const struct mlx5_flow_driver_ops *fops;
    9126                 :            : 
    9127                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9128                 :          0 :         return fops->create_meter(dev);
    9129                 :            : }
    9130                 :            : 
    9131                 :            : /**
    9132                 :            :  * Free the aso flow meter id.
    9133                 :            :  *
    9134                 :            :  * @param[in] dev
    9135                 :            :  *   Pointer to Ethernet device.
    9136                 :            :  * @param[in] mtr_idx
    9137                 :            :  *  Index to aso flow meter to be free.
    9138                 :            :  *
    9139                 :            :  * @return
    9140                 :            :  *   0 on success.
    9141                 :            :  */
    9142                 :            : void
    9143                 :          0 : mlx5_flow_mtr_free(struct rte_eth_dev *dev, uint32_t mtr_idx)
    9144                 :            : {
    9145                 :            :         const struct mlx5_flow_driver_ops *fops;
    9146                 :            : 
    9147                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
    9148                 :          0 :         fops->free_meter(dev, mtr_idx);
    9149                 :          0 : }
    9150                 :            : 
    9151                 :            : /**
    9152                 :            :  * Allocate a counter.
    9153                 :            :  *
    9154                 :            :  * @param[in] dev
    9155                 :            :  *   Pointer to Ethernet device structure.
    9156                 :            :  *
    9157                 :            :  * @return
    9158                 :            :  *   Index to allocated counter  on success, 0 otherwise.
    9159                 :            :  */
    9160                 :            : uint32_t
    9161         [ #  # ]:          0 : mlx5_counter_alloc(struct rte_eth_dev *dev)
    9162                 :            : {
    9163                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
    9164                 :            : 
    9165                 :          0 :         return flow_get_drv_ops(flow_get_drv_type(dev, &attr))->counter_alloc
    9166                 :            :                 (dev);
    9167                 :            : }
    9168                 :            : 
    9169                 :            : /**
    9170                 :            :  * Free a counter.
    9171                 :            :  *
    9172                 :            :  * @param[in] dev
    9173                 :            :  *   Pointer to Ethernet device structure.
    9174                 :            :  * @param[in] cnt
    9175                 :            :  *   Index to counter to be free.
    9176                 :            :  */
    9177                 :            : void
    9178         [ #  # ]:          0 : mlx5_counter_free(struct rte_eth_dev *dev, uint32_t cnt)
    9179                 :            : {
    9180                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
    9181                 :            : 
    9182                 :          0 :         flow_get_drv_ops(flow_get_drv_type(dev, &attr))->counter_free(dev, cnt);
    9183                 :          0 : }
    9184                 :            : 
    9185                 :            : /**
    9186                 :            :  * Query counter statistics.
    9187                 :            :  *
    9188                 :            :  * @param[in] dev
    9189                 :            :  *   Pointer to Ethernet device structure.
    9190                 :            :  * @param[in] cnt
    9191                 :            :  *   Index to counter to query.
    9192                 :            :  * @param[in] clear
    9193                 :            :  *   Set to clear counter statistics.
    9194                 :            :  * @param[out] pkts
    9195                 :            :  *   The counter hits packets number to save.
    9196                 :            :  * @param[out] bytes
    9197                 :            :  *   The counter hits bytes number to save.
    9198                 :            :  *
    9199                 :            :  * @return
    9200                 :            :  *   0 on success, a negative errno value otherwise.
    9201                 :            :  */
    9202                 :            : int
    9203         [ #  # ]:          0 : mlx5_counter_query(struct rte_eth_dev *dev, uint32_t cnt,
    9204                 :            :                    bool clear, uint64_t *pkts, uint64_t *bytes, void **action)
    9205                 :            : {
    9206                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
    9207                 :            : 
    9208                 :          0 :         return flow_get_drv_ops(flow_get_drv_type(dev, &attr))->counter_query
    9209                 :            :                 (dev, cnt, clear, pkts, bytes, action);
    9210                 :            : }
    9211                 :            : 
    9212                 :            : /**
    9213                 :            :  * Get information about HWS pre-configurable resources.
    9214                 :            :  *
    9215                 :            :  * @param[in] dev
    9216                 :            :  *   Pointer to the rte_eth_dev structure.
    9217                 :            :  * @param[out] port_info
    9218                 :            :  *   Pointer to port information.
    9219                 :            :  * @param[out] queue_info
    9220                 :            :  *   Pointer to queue information.
    9221                 :            :  * @param[out] error
    9222                 :            :  *   Pointer to error structure.
    9223                 :            :  *
    9224                 :            :  * @return
    9225                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9226                 :            :  */
    9227                 :            : static int
    9228         [ #  # ]:          0 : mlx5_flow_info_get(struct rte_eth_dev *dev,
    9229                 :            :                    struct rte_flow_port_info *port_info,
    9230                 :            :                    struct rte_flow_queue_info *queue_info,
    9231                 :            :                    struct rte_flow_error *error)
    9232                 :            : {
    9233                 :            :         const struct mlx5_flow_driver_ops *fops;
    9234                 :            :         struct rte_flow_attr attr = {0};
    9235                 :            : 
    9236                 :            :         if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW)
    9237                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9238                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9239                 :            :                                 NULL,
    9240                 :            :                                 "info get with incorrect steering mode");
    9241                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9242                 :          0 :         return fops->info_get(dev, port_info, queue_info, error);
    9243                 :            : }
    9244                 :            : 
    9245                 :            : /**
    9246                 :            :  * Configure port HWS resources.
    9247                 :            :  *
    9248                 :            :  * @param[in] dev
    9249                 :            :  *   Pointer to the rte_eth_dev structure.
    9250                 :            :  * @param[in] port_attr
    9251                 :            :  *   Port configuration attributes.
    9252                 :            :  * @param[in] nb_queue
    9253                 :            :  *   Number of queue.
    9254                 :            :  * @param[in] queue_attr
    9255                 :            :  *   Array that holds attributes for each flow queue.
    9256                 :            :  * @param[out] error
    9257                 :            :  *   Pointer to error structure.
    9258                 :            :  *
    9259                 :            :  * @return
    9260                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9261                 :            :  */
    9262                 :            : static int
    9263         [ #  # ]:          0 : mlx5_flow_port_configure(struct rte_eth_dev *dev,
    9264                 :            :                          const struct rte_flow_port_attr *port_attr,
    9265                 :            :                          uint16_t nb_queue,
    9266                 :            :                          const struct rte_flow_queue_attr *queue_attr[],
    9267                 :            :                          struct rte_flow_error *error)
    9268                 :            : {
    9269                 :            :         const struct mlx5_flow_driver_ops *fops;
    9270                 :            :         struct rte_flow_attr attr = {0};
    9271                 :            : 
    9272                 :            :         if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW)
    9273                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9274                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9275                 :            :                                 NULL,
    9276                 :            :                                 "port configure with incorrect steering mode");
    9277                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9278                 :          0 :         return fops->configure(dev, port_attr, nb_queue, queue_attr, error);
    9279                 :            : }
    9280                 :            : 
    9281                 :            : /**
    9282                 :            :  * Validate item template.
    9283                 :            :  *
    9284                 :            :  * @param[in] dev
    9285                 :            :  *   Pointer to the rte_eth_dev structure.
    9286                 :            :  * @param[in] attr
    9287                 :            :  *   Pointer to the item template attributes.
    9288                 :            :  * @param[in] items
    9289                 :            :  *   The template item pattern.
    9290                 :            :  * @param[out] error
    9291                 :            :  *   Pointer to error structure.
    9292                 :            :  *
    9293                 :            :  * @return
    9294                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9295                 :            :  */
    9296                 :            : int
    9297                 :          0 : mlx5_flow_pattern_validate(struct rte_eth_dev *dev,
    9298                 :            :                 const struct rte_flow_pattern_template_attr *attr,
    9299                 :            :                 const struct rte_flow_item items[],
    9300                 :            :                 struct rte_flow_error *error)
    9301                 :            : {
    9302                 :            :         const struct mlx5_flow_driver_ops *fops;
    9303                 :            :         struct rte_flow_attr fattr = {0};
    9304         [ #  # ]:          0 :         uint64_t item_flags = 0;
    9305                 :            : 
    9306                 :            :         if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) {
    9307                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    9308                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9309                 :            :                         "pattern validate with incorrect steering mode");
    9310                 :          0 :                 return -ENOTSUP;
    9311                 :            :         }
    9312                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9313                 :          0 :         return fops->pattern_validate(dev, attr, items, &item_flags, error);
    9314                 :            : }
    9315                 :            : 
    9316                 :            : /**
    9317                 :            :  * Create flow item template.
    9318                 :            :  *
    9319                 :            :  * @param[in] dev
    9320                 :            :  *   Pointer to the rte_eth_dev structure.
    9321                 :            :  * @param[in] attr
    9322                 :            :  *   Pointer to the item template attributes.
    9323                 :            :  * @param[in] items
    9324                 :            :  *   The template item pattern.
    9325                 :            :  * @param[out] error
    9326                 :            :  *   Pointer to error structure.
    9327                 :            :  *
    9328                 :            :  * @return
    9329                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9330                 :            :  */
    9331                 :            : static struct rte_flow_pattern_template *
    9332         [ #  # ]:          0 : mlx5_flow_pattern_template_create(struct rte_eth_dev *dev,
    9333                 :            :                 const struct rte_flow_pattern_template_attr *attr,
    9334                 :            :                 const struct rte_flow_item items[],
    9335                 :            :                 struct rte_flow_error *error)
    9336                 :            : {
    9337                 :            :         const struct mlx5_flow_driver_ops *fops;
    9338                 :            :         struct rte_flow_attr fattr = {0};
    9339                 :            : 
    9340                 :            :         if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) {
    9341                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    9342                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9343                 :            :                                 NULL,
    9344                 :            :                                 "pattern create with incorrect steering mode");
    9345                 :          0 :                 return NULL;
    9346                 :            :         }
    9347                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9348                 :          0 :         return fops->pattern_template_create(dev, attr, items, error);
    9349                 :            : }
    9350                 :            : 
    9351                 :            : /**
    9352                 :            :  * Destroy flow item template.
    9353                 :            :  *
    9354                 :            :  * @param[in] dev
    9355                 :            :  *   Pointer to the rte_eth_dev structure.
    9356                 :            :  * @param[in] template
    9357                 :            :  *   Pointer to the item template to be destroyed.
    9358                 :            :  * @param[out] error
    9359                 :            :  *   Pointer to error structure.
    9360                 :            :  *
    9361                 :            :  * @return
    9362                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9363                 :            :  */
    9364                 :            : static int
    9365         [ #  # ]:          0 : mlx5_flow_pattern_template_destroy(struct rte_eth_dev *dev,
    9366                 :            :                                    struct rte_flow_pattern_template *template,
    9367                 :            :                                    struct rte_flow_error *error)
    9368                 :            : {
    9369                 :            :         const struct mlx5_flow_driver_ops *fops;
    9370                 :            :         struct rte_flow_attr attr = {0};
    9371                 :            : 
    9372                 :            :         if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW)
    9373                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9374                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9375                 :            :                                 NULL,
    9376                 :            :                                 "pattern destroy with incorrect steering mode");
    9377                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9378                 :          0 :         return fops->pattern_template_destroy(dev, template, error);
    9379                 :            : }
    9380                 :            : 
    9381                 :            : /**
    9382                 :            :  * Validate flow actions template.
    9383                 :            :  *
    9384                 :            :  * @param[in] dev
    9385                 :            :  *   Pointer to the rte_eth_dev structure.
    9386                 :            :  * @param[in] attr
    9387                 :            :  *   Pointer to the action template attributes.
    9388                 :            :  * @param[in] actions
    9389                 :            :  *   Associated actions (list terminated by the END action).
    9390                 :            :  * @param[in] masks
    9391                 :            :  *   List of actions that marks which of the action's member is constant.
    9392                 :            :  * @param[out] error
    9393                 :            :  *   Pointer to error structure.
    9394                 :            :  *
    9395                 :            :  * @return
    9396                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9397                 :            :  */
    9398                 :            : int
    9399         [ #  # ]:          0 : mlx5_flow_actions_validate(struct rte_eth_dev *dev,
    9400                 :            :                         const struct rte_flow_actions_template_attr *attr,
    9401                 :            :                         const struct rte_flow_action actions[],
    9402                 :            :                         const struct rte_flow_action masks[],
    9403                 :            :                         struct rte_flow_error *error)
    9404                 :            : {
    9405                 :            :         const struct mlx5_flow_driver_ops *fops;
    9406                 :            :         struct rte_flow_attr fattr = {0};
    9407                 :            : 
    9408                 :            :         if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) {
    9409                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    9410                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9411                 :            :                         "actions validate with incorrect steering mode");
    9412                 :          0 :                 return -ENOTSUP;
    9413                 :            :         }
    9414                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9415                 :          0 :         return fops->actions_validate(dev, attr, actions, masks, error);
    9416                 :            : }
    9417                 :            : 
    9418                 :            : /**
    9419                 :            :  * Create flow item template.
    9420                 :            :  *
    9421                 :            :  * @param[in] dev
    9422                 :            :  *   Pointer to the rte_eth_dev structure.
    9423                 :            :  * @param[in] attr
    9424                 :            :  *   Pointer to the action template attributes.
    9425                 :            :  * @param[in] actions
    9426                 :            :  *   Associated actions (list terminated by the END action).
    9427                 :            :  * @param[in] masks
    9428                 :            :  *   List of actions that marks which of the action's member is constant.
    9429                 :            :  * @param[out] error
    9430                 :            :  *   Pointer to error structure.
    9431                 :            :  *
    9432                 :            :  * @return
    9433                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9434                 :            :  */
    9435                 :            : static struct rte_flow_actions_template *
    9436         [ #  # ]:          0 : mlx5_flow_actions_template_create(struct rte_eth_dev *dev,
    9437                 :            :                         const struct rte_flow_actions_template_attr *attr,
    9438                 :            :                         const struct rte_flow_action actions[],
    9439                 :            :                         const struct rte_flow_action masks[],
    9440                 :            :                         struct rte_flow_error *error)
    9441                 :            : {
    9442                 :            :         const struct mlx5_flow_driver_ops *fops;
    9443                 :            :         struct rte_flow_attr fattr = {0};
    9444                 :            : 
    9445                 :            :         if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) {
    9446                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    9447                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9448                 :            :                                 NULL,
    9449                 :            :                                 "action create with incorrect steering mode");
    9450                 :          0 :                 return NULL;
    9451                 :            :         }
    9452                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9453                 :          0 :         return fops->actions_template_create(dev, attr, actions, masks, error);
    9454                 :            : }
    9455                 :            : 
    9456                 :            : /**
    9457                 :            :  * Destroy flow action template.
    9458                 :            :  *
    9459                 :            :  * @param[in] dev
    9460                 :            :  *   Pointer to the rte_eth_dev structure.
    9461                 :            :  * @param[in] template
    9462                 :            :  *   Pointer to the action template to be destroyed.
    9463                 :            :  * @param[out] error
    9464                 :            :  *   Pointer to error structure.
    9465                 :            :  *
    9466                 :            :  * @return
    9467                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9468                 :            :  */
    9469                 :            : static int
    9470         [ #  # ]:          0 : mlx5_flow_actions_template_destroy(struct rte_eth_dev *dev,
    9471                 :            :                                    struct rte_flow_actions_template *template,
    9472                 :            :                                    struct rte_flow_error *error)
    9473                 :            : {
    9474                 :            :         const struct mlx5_flow_driver_ops *fops;
    9475                 :            :         struct rte_flow_attr attr = {0};
    9476                 :            : 
    9477                 :            :         if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW)
    9478                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9479                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9480                 :            :                                 NULL,
    9481                 :            :                                 "action destroy with incorrect steering mode");
    9482                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9483                 :          0 :         return fops->actions_template_destroy(dev, template, error);
    9484                 :            : }
    9485                 :            : 
    9486                 :            : /**
    9487                 :            :  * Create flow table.
    9488                 :            :  *
    9489                 :            :  * @param[in] dev
    9490                 :            :  *   Pointer to the rte_eth_dev structure.
    9491                 :            :  * @param[in] attr
    9492                 :            :  *   Pointer to the table attributes.
    9493                 :            :  * @param[in] item_templates
    9494                 :            :  *   Item template array to be binded to the table.
    9495                 :            :  * @param[in] nb_item_templates
    9496                 :            :  *   Number of item template.
    9497                 :            :  * @param[in] action_templates
    9498                 :            :  *   Action template array to be binded to the table.
    9499                 :            :  * @param[in] nb_action_templates
    9500                 :            :  *   Number of action template.
    9501                 :            :  * @param[out] error
    9502                 :            :  *   Pointer to error structure.
    9503                 :            :  *
    9504                 :            :  * @return
    9505                 :            :  *    Table on success, NULL otherwise and rte_errno is set.
    9506                 :            :  */
    9507                 :            : static struct rte_flow_template_table *
    9508         [ #  # ]:          0 : mlx5_flow_table_create(struct rte_eth_dev *dev,
    9509                 :            :                        const struct rte_flow_template_table_attr *attr,
    9510                 :            :                        struct rte_flow_pattern_template *item_templates[],
    9511                 :            :                        uint8_t nb_item_templates,
    9512                 :            :                        struct rte_flow_actions_template *action_templates[],
    9513                 :            :                        uint8_t nb_action_templates,
    9514                 :            :                        struct rte_flow_error *error)
    9515                 :            : {
    9516                 :            :         const struct mlx5_flow_driver_ops *fops;
    9517                 :            :         struct rte_flow_attr fattr = {0};
    9518                 :            : 
    9519                 :            :         if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) {
    9520                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    9521                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9522                 :            :                                 NULL,
    9523                 :            :                                 "table create with incorrect steering mode");
    9524                 :          0 :                 return NULL;
    9525                 :            :         }
    9526                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9527                 :          0 :         return fops->template_table_create(dev,
    9528                 :            :                                            attr,
    9529                 :            :                                            item_templates,
    9530                 :            :                                            nb_item_templates,
    9531                 :            :                                            action_templates,
    9532                 :            :                                            nb_action_templates,
    9533                 :            :                                            error);
    9534                 :            : }
    9535                 :            : 
    9536                 :            : /**
    9537                 :            :  * PMD destroy flow table.
    9538                 :            :  *
    9539                 :            :  * @param[in] dev
    9540                 :            :  *   Pointer to the rte_eth_dev structure.
    9541                 :            :  * @param[in] table
    9542                 :            :  *   Pointer to the table to be destroyed.
    9543                 :            :  * @param[out] error
    9544                 :            :  *   Pointer to error structure.
    9545                 :            :  *
    9546                 :            :  * @return
    9547                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9548                 :            :  */
    9549                 :            : static int
    9550         [ #  # ]:          0 : mlx5_flow_table_destroy(struct rte_eth_dev *dev,
    9551                 :            :                         struct rte_flow_template_table *table,
    9552                 :            :                         struct rte_flow_error *error)
    9553                 :            : {
    9554                 :            :         const struct mlx5_flow_driver_ops *fops;
    9555                 :            :         struct rte_flow_attr attr = {0};
    9556                 :            : 
    9557                 :            :         if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW)
    9558                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9559                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9560                 :            :                                 NULL,
    9561                 :            :                                 "table destroy with incorrect steering mode");
    9562                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9563                 :          0 :         return fops->template_table_destroy(dev, table, error);
    9564                 :            : }
    9565                 :            : 
    9566                 :            : /**
    9567                 :            :  * PMD group set miss actions.
    9568                 :            :  *
    9569                 :            :  * @param[in] dev
    9570                 :            :  *   Pointer to the rte_eth_dev structure.
    9571                 :            :  * @param[in] attr
    9572                 :            :  *   Pointer to group attributes
    9573                 :            :  * @param[in] actions
    9574                 :            :  *   Array of actions
    9575                 :            :  * @param[out] error
    9576                 :            :  *   Pointer to error structure.
    9577                 :            :  *
    9578                 :            :  * @return
    9579                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9580                 :            :  */
    9581                 :            : static int
    9582         [ #  # ]:          0 : mlx5_flow_group_set_miss_actions(struct rte_eth_dev *dev,
    9583                 :            :                                  uint32_t group_id,
    9584                 :            :                                  const struct rte_flow_group_attr *attr,
    9585                 :            :                                  const struct rte_flow_action actions[],
    9586                 :            :                                  struct rte_flow_error *error)
    9587                 :            : {
    9588                 :            :         const struct mlx5_flow_driver_ops *fops;
    9589                 :            :         struct rte_flow_attr fattr = {0};
    9590                 :            : 
    9591                 :            :         if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW)
    9592                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9593                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    9594                 :            :                                 NULL,
    9595                 :            :                                 "group set miss actions with incorrect steering mode");
    9596                 :          0 :         fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
    9597                 :          0 :         return fops->group_set_miss_actions(dev, group_id, attr, actions, error);
    9598                 :            : }
    9599                 :            : 
    9600                 :            : /**
    9601                 :            :  * Allocate a new memory for the counter values wrapped by all the needed
    9602                 :            :  * management.
    9603                 :            :  *
    9604                 :            :  * @param[in] sh
    9605                 :            :  *   Pointer to mlx5_dev_ctx_shared object.
    9606                 :            :  *
    9607                 :            :  * @return
    9608                 :            :  *   0 on success, a negative errno value otherwise.
    9609                 :            :  */
    9610                 :            : static int
    9611                 :          0 : mlx5_flow_create_counter_stat_mem_mng(struct mlx5_dev_ctx_shared *sh)
    9612                 :            : {
    9613                 :            :         struct mlx5_counter_stats_mem_mng *mem_mng;
    9614                 :            :         volatile struct flow_counter_stats *raw_data;
    9615                 :            :         int raws_n = MLX5_CNT_MR_ALLOC_BULK + MLX5_MAX_PENDING_QUERIES;
    9616                 :            :         int size = (sizeof(struct flow_counter_stats) *
    9617                 :            :                         MLX5_COUNTERS_PER_POOL +
    9618                 :            :                         sizeof(struct mlx5_counter_stats_raw)) * raws_n +
    9619                 :            :                         sizeof(struct mlx5_counter_stats_mem_mng);
    9620                 :          0 :         size_t pgsize = rte_mem_page_size();
    9621                 :            :         uint8_t *mem;
    9622                 :            :         int ret;
    9623                 :            :         int i;
    9624                 :            : 
    9625         [ #  # ]:          0 :         if (pgsize == (size_t)-1) {
    9626                 :          0 :                 DRV_LOG(ERR, "Failed to get mem page size");
    9627                 :          0 :                 rte_errno = ENOMEM;
    9628                 :          0 :                 return -ENOMEM;
    9629                 :            :         }
    9630                 :          0 :         mem = mlx5_malloc(MLX5_MEM_ZERO, size, pgsize, SOCKET_ID_ANY);
    9631         [ #  # ]:          0 :         if (!mem) {
    9632                 :          0 :                 rte_errno = ENOMEM;
    9633                 :          0 :                 return -ENOMEM;
    9634                 :            :         }
    9635                 :          0 :         mem_mng = (struct mlx5_counter_stats_mem_mng *)(mem + size) - 1;
    9636                 :            :         size = sizeof(*raw_data) * MLX5_COUNTERS_PER_POOL * raws_n;
    9637                 :          0 :         ret = mlx5_os_wrapped_mkey_create(sh->cdev->ctx, sh->cdev->pd,
    9638                 :          0 :                                           sh->cdev->pdn, mem, size,
    9639                 :            :                                           &mem_mng->wm);
    9640         [ #  # ]:          0 :         if (ret) {
    9641                 :          0 :                 rte_errno = errno;
    9642                 :          0 :                 mlx5_free(mem);
    9643                 :          0 :                 return -rte_errno;
    9644                 :            :         }
    9645                 :          0 :         mem_mng->raws = (struct mlx5_counter_stats_raw *)(mem + size);
    9646                 :            :         raw_data = (volatile struct flow_counter_stats *)mem;
    9647         [ #  # ]:          0 :         for (i = 0; i < raws_n; ++i) {
    9648                 :          0 :                 mem_mng->raws[i].mem_mng = mem_mng;
    9649                 :          0 :                 mem_mng->raws[i].data = raw_data + i * MLX5_COUNTERS_PER_POOL;
    9650                 :            :         }
    9651         [ #  # ]:          0 :         for (i = 0; i < MLX5_MAX_PENDING_QUERIES; ++i)
    9652         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&sh->sws_cmng.free_stat_raws,
    9653                 :            :                                  mem_mng->raws + MLX5_CNT_MR_ALLOC_BULK + i,
    9654                 :            :                                  next);
    9655         [ #  # ]:          0 :         LIST_INSERT_HEAD(&sh->sws_cmng.mem_mngs, mem_mng, next);
    9656                 :          0 :         sh->sws_cmng.mem_mng = mem_mng;
    9657                 :          0 :         return 0;
    9658                 :            : }
    9659                 :            : 
    9660                 :            : /**
    9661                 :            :  * Set the statistic memory to the new counter pool.
    9662                 :            :  *
    9663                 :            :  * @param[in] sh
    9664                 :            :  *   Pointer to mlx5_dev_ctx_shared object.
    9665                 :            :  * @param[in] pool
    9666                 :            :  *   Pointer to the pool to set the statistic memory.
    9667                 :            :  *
    9668                 :            :  * @return
    9669                 :            :  *   0 on success, a negative errno value otherwise.
    9670                 :            :  */
    9671                 :            : static int
    9672                 :          0 : mlx5_flow_set_counter_stat_mem(struct mlx5_dev_ctx_shared *sh,
    9673                 :            :                                struct mlx5_flow_counter_pool *pool)
    9674                 :            : {
    9675                 :            :         struct mlx5_flow_counter_mng *cmng = &sh->sws_cmng;
    9676                 :            :         /* Resize statistic memory once used out. */
    9677   [ #  #  #  # ]:          0 :         if (!(pool->index % MLX5_CNT_MR_ALLOC_BULK) &&
    9678                 :          0 :             mlx5_flow_create_counter_stat_mem_mng(sh)) {
    9679                 :          0 :                 DRV_LOG(ERR, "Cannot resize counter stat mem.");
    9680                 :          0 :                 return -1;
    9681                 :            :         }
    9682                 :          0 :         rte_spinlock_lock(&pool->sl);
    9683                 :          0 :         pool->raw = cmng->mem_mng->raws + pool->index % MLX5_CNT_MR_ALLOC_BULK;
    9684                 :            :         rte_spinlock_unlock(&pool->sl);
    9685                 :          0 :         pool->raw_hw = NULL;
    9686                 :          0 :         return 0;
    9687                 :            : }
    9688                 :            : 
    9689                 :            : #define MLX5_POOL_QUERY_FREQ_US 1000000
    9690                 :            : 
    9691                 :            : /**
    9692                 :            :  * Set the periodic procedure for triggering asynchronous batch queries for all
    9693                 :            :  * the counter pools.
    9694                 :            :  *
    9695                 :            :  * @param[in] sh
    9696                 :            :  *   Pointer to mlx5_dev_ctx_shared object.
    9697                 :            :  */
    9698                 :            : void
    9699                 :          0 : mlx5_set_query_alarm(struct mlx5_dev_ctx_shared *sh)
    9700                 :            : {
    9701                 :            :         uint32_t pools_n, us;
    9702                 :            : 
    9703                 :          0 :         pools_n = rte_atomic_load_explicit(&sh->sws_cmng.n_valid, rte_memory_order_relaxed);
    9704                 :          0 :         us = MLX5_POOL_QUERY_FREQ_US / pools_n;
    9705                 :          0 :         DRV_LOG(DEBUG, "Set alarm for %u pools each %u us", pools_n, us);
    9706         [ #  # ]:          0 :         if (rte_eal_alarm_set(us, mlx5_flow_query_alarm, sh)) {
    9707                 :          0 :                 sh->sws_cmng.query_thread_on = 0;
    9708                 :          0 :                 DRV_LOG(ERR, "Cannot reinitialize query alarm");
    9709                 :            :         } else {
    9710                 :          0 :                 sh->sws_cmng.query_thread_on = 1;
    9711                 :            :         }
    9712                 :          0 : }
    9713                 :            : 
    9714                 :            : /**
    9715                 :            :  * The periodic procedure for triggering asynchronous batch queries for all the
    9716                 :            :  * counter pools. This function is probably called by the host thread.
    9717                 :            :  *
    9718                 :            :  * @param[in] arg
    9719                 :            :  *   The parameter for the alarm process.
    9720                 :            :  */
    9721                 :            : void
    9722                 :          0 : mlx5_flow_query_alarm(void *arg)
    9723                 :            : {
    9724                 :            :         struct mlx5_dev_ctx_shared *sh = arg;
    9725                 :            :         struct mlx5_flow_counter_mng *cmng = &sh->sws_cmng;
    9726                 :          0 :         uint16_t pool_index = cmng->pool_index;
    9727                 :            :         struct mlx5_flow_counter_pool *pool;
    9728                 :            :         uint16_t n_valid;
    9729                 :            :         int ret;
    9730                 :            : 
    9731         [ #  # ]:          0 :         if (cmng->pending_queries >= MLX5_MAX_PENDING_QUERIES)
    9732                 :          0 :                 goto set_alarm;
    9733                 :          0 :         rte_spinlock_lock(&cmng->pool_update_sl);
    9734                 :          0 :         pool = cmng->pools[pool_index];
    9735                 :          0 :         n_valid = cmng->n_valid;
    9736                 :            :         rte_spinlock_unlock(&cmng->pool_update_sl);
    9737                 :            :         /* Set the statistic memory to the new created pool. */
    9738   [ #  #  #  # ]:          0 :         if ((!pool->raw && mlx5_flow_set_counter_stat_mem(sh, pool)))
    9739                 :          0 :                 goto set_alarm;
    9740         [ #  # ]:          0 :         if (pool->raw_hw)
    9741                 :            :                 /* There is a pool query in progress. */
    9742                 :          0 :                 goto set_alarm;
    9743                 :          0 :         pool->raw_hw = LIST_FIRST(&cmng->free_stat_raws);
    9744         [ #  # ]:          0 :         if (!pool->raw_hw)
    9745                 :            :                 /* No free counter statistics raw memory. */
    9746                 :          0 :                 goto set_alarm;
    9747                 :            :         /*
    9748                 :            :          * Identify the counters released between query trigger and query
    9749                 :            :          * handle more efficiently. The counter released in this gap period
    9750                 :            :          * should wait for a new round of query as the new arrived packets
    9751                 :            :          * will not be taken into account.
    9752                 :            :          */
    9753                 :          0 :         pool->query_gen++;
    9754                 :          0 :         ret = mlx5_devx_cmd_flow_counter_query(pool->min_dcs, 0,
    9755                 :            :                                                MLX5_COUNTERS_PER_POOL,
    9756                 :            :                                                NULL, NULL,
    9757                 :          0 :                                                pool->raw_hw->mem_mng->wm.lkey,
    9758                 :            :                                                (void *)(uintptr_t)
    9759                 :          0 :                                                pool->raw_hw->data,
    9760                 :            :                                                sh->devx_comp,
    9761                 :            :                                                (uint64_t)(uintptr_t)pool);
    9762         [ #  # ]:          0 :         if (ret) {
    9763                 :          0 :                 DRV_LOG(ERR, "Failed to trigger asynchronous query for dcs ID"
    9764                 :            :                         " %d", pool->min_dcs->id);
    9765                 :          0 :                 pool->raw_hw = NULL;
    9766                 :          0 :                 goto set_alarm;
    9767                 :            :         }
    9768         [ #  # ]:          0 :         LIST_REMOVE(pool->raw_hw, next);
    9769                 :          0 :         cmng->pending_queries++;
    9770                 :          0 :         pool_index++;
    9771         [ #  # ]:          0 :         if (pool_index >= n_valid)
    9772                 :            :                 pool_index = 0;
    9773                 :          0 : set_alarm:
    9774                 :          0 :         cmng->pool_index = pool_index;
    9775                 :          0 :         mlx5_set_query_alarm(sh);
    9776                 :          0 : }
    9777                 :            : 
    9778                 :            : /**
    9779                 :            :  * Check and callback event for new aged flow in the counter pool
    9780                 :            :  *
    9781                 :            :  * @param[in] sh
    9782                 :            :  *   Pointer to mlx5_dev_ctx_shared object.
    9783                 :            :  * @param[in] pool
    9784                 :            :  *   Pointer to Current counter pool.
    9785                 :            :  */
    9786                 :            : static void
    9787                 :          0 : mlx5_flow_aging_check(struct mlx5_dev_ctx_shared *sh,
    9788                 :            :                    struct mlx5_flow_counter_pool *pool)
    9789                 :            : {
    9790                 :            :         struct mlx5_priv *priv;
    9791                 :            :         struct mlx5_flow_counter *cnt;
    9792                 :            :         struct mlx5_age_info *age_info;
    9793                 :            :         struct mlx5_age_param *age_param;
    9794                 :          0 :         struct mlx5_counter_stats_raw *cur = pool->raw_hw;
    9795                 :          0 :         struct mlx5_counter_stats_raw *prev = pool->raw;
    9796                 :          0 :         const uint64_t curr_time = MLX5_CURR_TIME_SEC;
    9797                 :          0 :         const uint32_t time_delta = curr_time - pool->time_of_last_age_check;
    9798                 :            :         uint16_t expected = AGE_CANDIDATE;
    9799                 :            :         uint32_t i;
    9800                 :            : 
    9801                 :          0 :         pool->time_of_last_age_check = curr_time;
    9802         [ #  # ]:          0 :         for (i = 0; i < MLX5_COUNTERS_PER_POOL; ++i) {
    9803         [ #  # ]:          0 :                 cnt = MLX5_POOL_GET_CNT(pool, i);
    9804                 :            :                 age_param = MLX5_CNT_TO_AGE(cnt);
    9805         [ #  # ]:          0 :                 if (rte_atomic_load_explicit(&age_param->state,
    9806                 :            :                                     rte_memory_order_relaxed) != AGE_CANDIDATE)
    9807                 :          0 :                         continue;
    9808         [ #  # ]:          0 :                 if (cur->data[i].hits != prev->data[i].hits) {
    9809                 :          0 :                         rte_atomic_store_explicit(&age_param->sec_since_last_hit, 0,
    9810                 :            :                                          rte_memory_order_relaxed);
    9811                 :          0 :                         continue;
    9812                 :            :                 }
    9813                 :          0 :                 if (rte_atomic_fetch_add_explicit(&age_param->sec_since_last_hit,
    9814                 :            :                                        time_delta,
    9815         [ #  # ]:          0 :                                        rte_memory_order_relaxed) + time_delta <= age_param->timeout)
    9816                 :          0 :                         continue;
    9817                 :            :                 /**
    9818                 :            :                  * Hold the lock first, or if between the
    9819                 :            :                  * state AGE_TMOUT and tailq operation the
    9820                 :            :                  * release happened, the release procedure
    9821                 :            :                  * may delete a non-existent tailq node.
    9822                 :            :                  */
    9823                 :          0 :                 priv = rte_eth_devices[age_param->port_id].data->dev_private;
    9824                 :          0 :                 age_info = GET_PORT_AGE_INFO(priv);
    9825                 :          0 :                 rte_spinlock_lock(&age_info->aged_sl);
    9826         [ #  # ]:          0 :                 if (rte_atomic_compare_exchange_strong_explicit(&age_param->state, &expected,
    9827                 :            :                                                 AGE_TMOUT,
    9828                 :            :                                                 rte_memory_order_relaxed,
    9829                 :            :                                                 rte_memory_order_relaxed)) {
    9830                 :          0 :                         TAILQ_INSERT_TAIL(&age_info->aged_counters, cnt, next);
    9831                 :          0 :                         MLX5_AGE_SET(age_info, MLX5_AGE_EVENT_NEW);
    9832                 :            :                 }
    9833                 :            :                 rte_spinlock_unlock(&age_info->aged_sl);
    9834                 :            :         }
    9835                 :          0 :         mlx5_age_event_prepare(sh);
    9836                 :          0 : }
    9837                 :            : 
    9838                 :            : /**
    9839                 :            :  * Handler for the HW respond about ready values from an asynchronous batch
    9840                 :            :  * query. This function is probably called by the host thread.
    9841                 :            :  *
    9842                 :            :  * @param[in] sh
    9843                 :            :  *   The pointer to the shared device context.
    9844                 :            :  * @param[in] async_id
    9845                 :            :  *   The Devx async ID.
    9846                 :            :  * @param[in] status
    9847                 :            :  *   The status of the completion.
    9848                 :            :  */
    9849                 :            : void
    9850                 :          0 : mlx5_flow_async_pool_query_handle(struct mlx5_dev_ctx_shared *sh,
    9851                 :            :                                   uint64_t async_id, int status)
    9852                 :            : {
    9853                 :          0 :         struct mlx5_flow_counter_pool *pool =
    9854                 :            :                 (struct mlx5_flow_counter_pool *)(uintptr_t)async_id;
    9855                 :            :         struct mlx5_counter_stats_raw *raw_to_free;
    9856                 :          0 :         uint8_t query_gen = pool->query_gen ^ 1;
    9857                 :            :         struct mlx5_flow_counter_mng *cmng = &sh->sws_cmng;
    9858                 :          0 :         enum mlx5_counter_type cnt_type =
    9859                 :          0 :                 pool->is_aged ? MLX5_COUNTER_TYPE_AGE :
    9860                 :            :                                 MLX5_COUNTER_TYPE_ORIGIN;
    9861                 :            : 
    9862         [ #  # ]:          0 :         if (unlikely(status)) {
    9863                 :          0 :                 raw_to_free = pool->raw_hw;
    9864                 :            :         } else {
    9865                 :          0 :                 raw_to_free = pool->raw;
    9866         [ #  # ]:          0 :                 if (pool->is_aged)
    9867                 :          0 :                         mlx5_flow_aging_check(sh, pool);
    9868                 :          0 :                 rte_spinlock_lock(&pool->sl);
    9869                 :          0 :                 pool->raw = pool->raw_hw;
    9870                 :            :                 rte_spinlock_unlock(&pool->sl);
    9871                 :            :                 /* Be sure the new raw counters data is updated in memory. */
    9872                 :          0 :                 rte_io_wmb();
    9873         [ #  # ]:          0 :                 if (!TAILQ_EMPTY(&pool->counters[query_gen])) {
    9874                 :          0 :                         rte_spinlock_lock(&cmng->csl[cnt_type]);
    9875         [ #  # ]:          0 :                         TAILQ_CONCAT(&cmng->counters[cnt_type],
    9876                 :            :                                      &pool->counters[query_gen], next);
    9877                 :            :                         rte_spinlock_unlock(&cmng->csl[cnt_type]);
    9878                 :            :                 }
    9879                 :            :         }
    9880         [ #  # ]:          0 :         LIST_INSERT_HEAD(&sh->sws_cmng.free_stat_raws, raw_to_free, next);
    9881                 :          0 :         pool->raw_hw = NULL;
    9882                 :          0 :         sh->sws_cmng.pending_queries--;
    9883                 :          0 : }
    9884                 :            : 
    9885                 :            : static int
    9886                 :          0 : flow_group_to_table(uint32_t port_id, uint32_t group, uint32_t *table,
    9887                 :            :                     const struct flow_grp_info *grp_info,
    9888                 :            :                     struct rte_flow_error *error)
    9889                 :            : {
    9890         [ #  # ]:          0 :         if (grp_info->transfer && grp_info->external &&
    9891                 :            :             grp_info->fdb_def_rule) {
    9892         [ #  # ]:          0 :                 if (group == UINT32_MAX)
    9893                 :          0 :                         return rte_flow_error_set
    9894                 :            :                                                 (error, EINVAL,
    9895                 :            :                                                  RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
    9896                 :            :                                                  NULL,
    9897                 :            :                                                  "group index not supported");
    9898                 :          0 :                 *table = group + 1;
    9899                 :            :         } else {
    9900                 :          0 :                 *table = group;
    9901                 :            :         }
    9902                 :          0 :         DRV_LOG(DEBUG, "port %u group=%#x table=%#x", port_id, group, *table);
    9903                 :          0 :         return 0;
    9904                 :            : }
    9905                 :            : 
    9906                 :            : /**
    9907                 :            :  * Translate the rte_flow group index to HW table value.
    9908                 :            :  *
    9909                 :            :  * If tunnel offload is disabled, all group ids converted to flow table
    9910                 :            :  * id using the standard method.
    9911                 :            :  * If tunnel offload is enabled, group id can be converted using the
    9912                 :            :  * standard or tunnel conversion method. Group conversion method
    9913                 :            :  * selection depends on flags in `grp_info` parameter:
    9914                 :            :  * - Internal (grp_info.external == 0) groups conversion uses the
    9915                 :            :  *   standard method.
    9916                 :            :  * - Group ids in JUMP action converted with the tunnel conversion.
    9917                 :            :  * - Group id in rule attribute conversion depends on a rule type and
    9918                 :            :  *   group id value:
    9919                 :            :  *   ** non zero group attributes converted with the tunnel method
    9920                 :            :  *   ** zero group attribute in non-tunnel rule is converted using the
    9921                 :            :  *      standard method - there's only one root table
    9922                 :            :  *   ** zero group attribute in steer tunnel rule is converted with the
    9923                 :            :  *      standard method - single root table
    9924                 :            :  *   ** zero group attribute in match tunnel rule is a special OvS
    9925                 :            :  *      case: that value is used for portability reasons. That group
    9926                 :            :  *      id is converted with the tunnel conversion method.
    9927                 :            :  *
    9928                 :            :  * @param[in] dev
    9929                 :            :  *   Port device
    9930                 :            :  * @param[in] tunnel
    9931                 :            :  *   PMD tunnel offload object
    9932                 :            :  * @param[in] group
    9933                 :            :  *   rte_flow group index value.
    9934                 :            :  * @param[out] table
    9935                 :            :  *   HW table value.
    9936                 :            :  * @param[in] grp_info
    9937                 :            :  *   flags used for conversion
    9938                 :            :  * @param[out] error
    9939                 :            :  *   Pointer to error structure.
    9940                 :            :  *
    9941                 :            :  * @return
    9942                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9943                 :            :  */
    9944                 :            : int
    9945                 :          0 : mlx5_flow_group_to_table(struct rte_eth_dev *dev,
    9946                 :            :                          const struct mlx5_flow_tunnel *tunnel,
    9947                 :            :                          uint32_t group, uint32_t *table,
    9948                 :            :                          const struct flow_grp_info *grp_info,
    9949                 :            :                          struct rte_flow_error *error)
    9950                 :            : {
    9951                 :            :         int ret;
    9952                 :            :         bool standard_translation;
    9953                 :            : 
    9954   [ #  #  #  # ]:          0 :         if (!grp_info->skip_scale && grp_info->external &&
    9955                 :            :             group < MLX5_MAX_TABLES_EXTERNAL)
    9956                 :          0 :                 group *= MLX5_FLOW_TABLE_FACTOR;
    9957         [ #  # ]:          0 :         if (is_tunnel_offload_active(dev)) {
    9958                 :          0 :                 standard_translation = !grp_info->external ||
    9959                 :            :                                         grp_info->std_tbl_fix;
    9960                 :            :         } else {
    9961                 :            :                 standard_translation = true;
    9962                 :            :         }
    9963         [ #  # ]:          0 :         DRV_LOG(DEBUG,
    9964                 :            :                 "port %u group=%u transfer=%d external=%d fdb_def_rule=%d translate=%s",
    9965                 :            :                 dev->data->port_id, group, grp_info->transfer,
    9966                 :            :                 grp_info->external, grp_info->fdb_def_rule,
    9967                 :            :                 standard_translation ? "STANDARD" : "TUNNEL");
    9968         [ #  # ]:          0 :         if (standard_translation)
    9969                 :          0 :                 ret = flow_group_to_table(dev->data->port_id, group, table,
    9970                 :            :                                           grp_info, error);
    9971                 :            :         else
    9972                 :          0 :                 ret = tunnel_flow_group_to_flow_table(dev, tunnel, group,
    9973                 :            :                                                       table, error);
    9974                 :            : 
    9975                 :          0 :         return ret;
    9976                 :            : }
    9977                 :            : 
    9978                 :            : /**
    9979                 :            :  * Discover availability of metadata reg_c's.
    9980                 :            :  *
    9981                 :            :  * Iteratively use test flows to check availability.
    9982                 :            :  *
    9983                 :            :  * @param[in] dev
    9984                 :            :  *   Pointer to the Ethernet device structure.
    9985                 :            :  *
    9986                 :            :  * @return
    9987                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    9988                 :            :  */
    9989                 :            : int
    9990                 :          0 : mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev)
    9991                 :            : {
    9992                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9993                 :            :         enum modify_reg idx;
    9994                 :            :         int n = 0;
    9995                 :            : 
    9996                 :            :         /* reg_c[0] and reg_c[1] are reserved. */
    9997                 :          0 :         priv->sh->flow_mreg_c[n++] = REG_C_0;
    9998                 :          0 :         priv->sh->flow_mreg_c[n++] = REG_C_1;
    9999                 :            :         /* Discover availability of other reg_c's. */
   10000         [ #  # ]:          0 :         for (idx = REG_C_2; idx <= REG_C_7; ++idx) {
   10001                 :          0 :                 struct rte_flow_attr attr = {
   10002                 :            :                         .group = MLX5_FLOW_MREG_CP_TABLE_GROUP,
   10003                 :            :                         .priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR,
   10004                 :            :                         .ingress = 1,
   10005                 :            :                 };
   10006                 :          0 :                 struct rte_flow_item items[] = {
   10007                 :            :                         [0] = {
   10008                 :            :                                 .type = RTE_FLOW_ITEM_TYPE_END,
   10009                 :            :                         },
   10010                 :            :                 };
   10011                 :          0 :                 struct rte_flow_action actions[] = {
   10012                 :            :                         [0] = {
   10013                 :            :                                 .type = (enum rte_flow_action_type)
   10014                 :            :                                         MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
   10015                 :          0 :                                 .conf = &(struct mlx5_flow_action_copy_mreg){
   10016                 :            :                                         .src = REG_C_1,
   10017                 :            :                                         .dst = idx,
   10018                 :            :                                 },
   10019                 :            :                         },
   10020                 :            :                         [1] = {
   10021                 :            :                                 .type = RTE_FLOW_ACTION_TYPE_JUMP,
   10022                 :          0 :                                 .conf = &(struct rte_flow_action_jump){
   10023                 :            :                                         .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP,
   10024                 :            :                                 },
   10025                 :            :                         },
   10026                 :            :                         [2] = {
   10027                 :            :                                 .type = RTE_FLOW_ACTION_TYPE_END,
   10028                 :            :                         },
   10029                 :            :                 };
   10030                 :            :                 uint32_t flow_idx;
   10031                 :            :                 struct rte_flow *flow;
   10032                 :            :                 struct rte_flow_error error;
   10033                 :            : 
   10034         [ #  # ]:          0 :                 if (!priv->sh->config.dv_flow_en)
   10035                 :            :                         break;
   10036                 :            :                 /* Create internal flow, validation skips copy action. */
   10037                 :          0 :                 flow_idx = mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_GEN, &attr,
   10038                 :            :                                         items, actions, false, &error);
   10039                 :          0 :                 flow = mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN],
   10040                 :            :                                       flow_idx);
   10041         [ #  # ]:          0 :                 if (!flow)
   10042                 :          0 :                         continue;
   10043                 :          0 :                 priv->sh->flow_mreg_c[n++] = idx;
   10044                 :          0 :                 mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN, flow_idx);
   10045                 :            :         }
   10046         [ #  # ]:          0 :         for (; n < MLX5_MREG_C_NUM; ++n)
   10047                 :          0 :                 priv->sh->flow_mreg_c[n] = REG_NON;
   10048                 :          0 :         priv->sh->metadata_regc_check_flag = 1;
   10049                 :          0 :         return 0;
   10050                 :            : }
   10051                 :            : 
   10052                 :            : int
   10053   [ #  #  #  # ]:          0 : save_dump_file(const uint8_t *data, uint32_t size,
   10054                 :            :         uint32_t type, uint64_t id, void *arg, FILE *file)
   10055                 :            : {
   10056                 :            :         char line[BUF_SIZE];
   10057                 :            :         uint32_t out = 0;
   10058                 :            :         uint32_t k;
   10059                 :            :         uint32_t actions_num;
   10060                 :            :         struct rte_flow_query_count *count;
   10061                 :            : 
   10062                 :            :         memset(line, 0, BUF_SIZE);
   10063   [ #  #  #  # ]:          0 :         switch (type) {
   10064                 :          0 :         case DR_DUMP_REC_TYPE_PMD_MODIFY_HDR:
   10065                 :          0 :                 actions_num = *(uint32_t *)(arg);
   10066                 :          0 :                 out += snprintf(line + out, BUF_SIZE - out, "%d,0x%" PRIx64 ",%d,",
   10067                 :            :                                 type, id, actions_num);
   10068                 :          0 :                 break;
   10069                 :          0 :         case DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT:
   10070                 :          0 :                 out += snprintf(line + out, BUF_SIZE - out, "%d,0x%" PRIx64 ",",
   10071                 :            :                                 type, id);
   10072                 :          0 :                 break;
   10073                 :          0 :         case DR_DUMP_REC_TYPE_PMD_COUNTER:
   10074                 :            :                 count = (struct rte_flow_query_count *)arg;
   10075                 :          0 :                 fprintf(file,
   10076                 :            :                         "%d,0x%" PRIx64 ",%" PRIu64 ",%" PRIu64 "\n",
   10077                 :            :                         type, id, count->hits, count->bytes);
   10078                 :          0 :                 return 0;
   10079                 :            :         default:
   10080                 :            :                 return -1;
   10081                 :            :         }
   10082                 :            : 
   10083         [ #  # ]:          0 :         for (k = 0; k < size; k++) {
   10084                 :            :                 /* Make sure we do not overrun the line buffer length. */
   10085         [ #  # ]:          0 :                 if (out >= BUF_SIZE - 4) {
   10086                 :          0 :                         line[out] = '\0';
   10087                 :          0 :                         break;
   10088                 :            :                 }
   10089                 :          0 :                 out += snprintf(line + out, BUF_SIZE - out, "%02x",
   10090                 :          0 :                                 (data[k]) & 0xff);
   10091                 :            :         }
   10092                 :            :         fprintf(file, "%s\n", line);
   10093                 :          0 :         return 0;
   10094                 :            : }
   10095                 :            : 
   10096                 :            : int
   10097                 :          0 : mlx5_flow_query_counter(struct rte_eth_dev *dev, struct rte_flow *flow,
   10098                 :            :         struct rte_flow_query_count *count, struct rte_flow_error *error)
   10099                 :            : {
   10100                 :            :         struct rte_flow_action action[2];
   10101                 :            :         enum mlx5_flow_drv_type ftype;
   10102                 :            :         const struct mlx5_flow_driver_ops *fops;
   10103                 :            : 
   10104         [ #  # ]:          0 :         if (!flow) {
   10105                 :          0 :                 return rte_flow_error_set(error, ENOENT,
   10106                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   10107                 :            :                                 NULL,
   10108                 :            :                                 "invalid flow handle");
   10109                 :            :         }
   10110                 :          0 :         action[0].type = RTE_FLOW_ACTION_TYPE_COUNT;
   10111                 :          0 :         action[1].type = RTE_FLOW_ACTION_TYPE_END;
   10112         [ #  # ]:          0 :         if (flow->counter) {
   10113                 :            :                 memset(count, 0, sizeof(struct rte_flow_query_count));
   10114                 :          0 :                 ftype = (enum mlx5_flow_drv_type)(flow->drv_type);
   10115                 :            :                 MLX5_ASSERT(ftype > MLX5_FLOW_TYPE_MIN &&
   10116                 :            :                                                 ftype < MLX5_FLOW_TYPE_MAX);
   10117                 :          0 :                 fops = flow_get_drv_ops(ftype);
   10118                 :          0 :                 return fops->query(dev, flow, action, count, error);
   10119                 :            :         }
   10120                 :            :         return -1;
   10121                 :            : }
   10122                 :            : 
   10123                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
   10124                 :            : /**
   10125                 :            :  * Dump flow ipool data to file
   10126                 :            :  *
   10127                 :            :  * @param[in] dev
   10128                 :            :  *   The pointer to Ethernet device.
   10129                 :            :  * @param[in] file
   10130                 :            :  *   A pointer to a file for output.
   10131                 :            :  * @param[out] error
   10132                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
   10133                 :            :  *   structure in case of error only.
   10134                 :            :  * @return
   10135                 :            :  *   0 on success, a negative value otherwise.
   10136                 :            :  */
   10137                 :            : int
   10138                 :          0 : mlx5_flow_dev_dump_ipool(struct rte_eth_dev *dev,
   10139                 :            :         struct rte_flow *flow, FILE *file,
   10140                 :            :         struct rte_flow_error *error)
   10141                 :            : {
   10142                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10143                 :            :         struct mlx5_flow_dv_modify_hdr_resource  *modify_hdr;
   10144                 :            :         struct mlx5_flow_dv_encap_decap_resource *encap_decap;
   10145                 :            :         uint32_t handle_idx;
   10146                 :            :         struct mlx5_flow_handle *dh;
   10147                 :            :         struct rte_flow_query_count count;
   10148                 :            :         uint32_t actions_num;
   10149                 :            :         const uint8_t *data;
   10150                 :            :         size_t size;
   10151                 :            :         uint64_t id;
   10152                 :            :         uint32_t type;
   10153                 :          0 :         void *action = NULL;
   10154                 :            : 
   10155         [ #  # ]:          0 :         if (!flow) {
   10156                 :          0 :                 return rte_flow_error_set(error, ENOENT,
   10157                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   10158                 :            :                                 NULL,
   10159                 :            :                                 "invalid flow handle");
   10160                 :            :         }
   10161                 :          0 :         handle_idx = flow->dev_handles;
   10162                 :            :         /* query counter */
   10163   [ #  #  #  # ]:          0 :         if (flow->counter &&
   10164                 :          0 :         (!mlx5_counter_query(dev, flow->counter, false,
   10165         [ #  # ]:          0 :         &count.hits, &count.bytes, &action)) && action) {
   10166                 :          0 :                 id = (uint64_t)(uintptr_t)action;
   10167                 :            :                 type = DR_DUMP_REC_TYPE_PMD_COUNTER;
   10168                 :          0 :                 save_dump_file(NULL, 0, type,
   10169                 :            :                         id, (void *)&count, file);
   10170                 :            :         }
   10171                 :            : 
   10172         [ #  # ]:          0 :         while (handle_idx) {
   10173                 :          0 :                 dh = mlx5_ipool_get(priv->sh->ipool
   10174                 :            :                                 [MLX5_IPOOL_MLX5_FLOW], handle_idx);
   10175         [ #  # ]:          0 :                 if (!dh)
   10176                 :          0 :                         continue;
   10177                 :          0 :                 handle_idx = dh->next.next;
   10178                 :            : 
   10179                 :            :                 /* Get modify_hdr and encap_decap buf from ipools. */
   10180                 :            :                 encap_decap = NULL;
   10181                 :          0 :                 modify_hdr = dh->dvh.modify_hdr;
   10182                 :            : 
   10183         [ #  # ]:          0 :                 if (dh->dvh.rix_encap_decap) {
   10184                 :          0 :                         encap_decap = mlx5_ipool_get(priv->sh->ipool
   10185                 :            :                                                 [MLX5_IPOOL_DECAP_ENCAP],
   10186                 :            :                                                 dh->dvh.rix_encap_decap);
   10187                 :            :                 }
   10188         [ #  # ]:          0 :                 if (modify_hdr) {
   10189                 :          0 :                         data = (const uint8_t *)modify_hdr->actions;
   10190                 :          0 :                         size = (size_t)(modify_hdr->actions_num) * 8;
   10191                 :          0 :                         id = (uint64_t)(uintptr_t)modify_hdr->action;
   10192                 :          0 :                         actions_num = modify_hdr->actions_num;
   10193                 :            :                         type = DR_DUMP_REC_TYPE_PMD_MODIFY_HDR;
   10194                 :          0 :                         save_dump_file(data, size, type, id,
   10195                 :            :                                                 (void *)(&actions_num), file);
   10196                 :            :                 }
   10197         [ #  # ]:          0 :                 if (encap_decap) {
   10198                 :          0 :                         data = encap_decap->buf;
   10199                 :          0 :                         size = encap_decap->size;
   10200                 :          0 :                         id = (uint64_t)(uintptr_t)encap_decap->action;
   10201                 :            :                         type = DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT;
   10202                 :          0 :                         save_dump_file(data, size, type,
   10203                 :            :                                                 id, NULL, file);
   10204                 :            :                 }
   10205                 :            :         }
   10206                 :            :         return 0;
   10207                 :            : }
   10208                 :            : 
   10209                 :            : /**
   10210                 :            :  * Dump all flow's encap_decap/modify_hdr/counter data to file
   10211                 :            :  *
   10212                 :            :  * @param[in] dev
   10213                 :            :  *   The pointer to Ethernet device.
   10214                 :            :  * @param[in] file
   10215                 :            :  *   A pointer to a file for output.
   10216                 :            :  * @param[out] error
   10217                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
   10218                 :            :  *   structure in case of error only.
   10219                 :            :  * @return
   10220                 :            :  *   0 on success, a negative value otherwise.
   10221                 :            :  */
   10222                 :            : static int
   10223                 :          0 : mlx5_flow_dev_dump_sh_all(struct rte_eth_dev *dev,
   10224                 :            :         FILE *file, struct rte_flow_error *error __rte_unused)
   10225                 :            : {
   10226                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10227                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   10228                 :            :         struct mlx5_hlist *h;
   10229                 :            :         struct mlx5_flow_dv_modify_hdr_resource  *modify_hdr;
   10230                 :            :         struct mlx5_flow_dv_encap_decap_resource *encap_decap;
   10231                 :            :         struct rte_flow_query_count count;
   10232                 :            :         uint32_t actions_num;
   10233                 :            :         const uint8_t *data;
   10234                 :            :         size_t size;
   10235                 :            :         uint64_t id;
   10236                 :            :         uint32_t type;
   10237                 :            :         uint32_t i;
   10238                 :            :         uint32_t j;
   10239                 :            :         struct mlx5_list_inconst *l_inconst;
   10240                 :            :         struct mlx5_list_entry *e;
   10241                 :            :         int lcore_index;
   10242                 :            :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
   10243                 :            :         uint32_t max;
   10244                 :            :         void *action;
   10245                 :            : 
   10246                 :            :         /* encap_decap hlist is lcore_share, get global core cache. */
   10247                 :            :         i = MLX5_LIST_GLOBAL;
   10248                 :          0 :         h = sh->encaps_decaps;
   10249         [ #  # ]:          0 :         if (h) {
   10250         [ #  # ]:          0 :                 for (j = 0; j <= h->mask; j++) {
   10251                 :            :                         l_inconst = &h->buckets[j].l;
   10252         [ #  # ]:          0 :                         if (!l_inconst || !l_inconst->cache[i])
   10253                 :          0 :                                 continue;
   10254                 :            : 
   10255                 :          0 :                         e = LIST_FIRST(&l_inconst->cache[i]->h);
   10256         [ #  # ]:          0 :                         while (e) {
   10257                 :            :                                 encap_decap =
   10258                 :            :                                 (struct mlx5_flow_dv_encap_decap_resource *)e;
   10259                 :          0 :                                 data = encap_decap->buf;
   10260                 :          0 :                                 size = encap_decap->size;
   10261                 :          0 :                                 id = (uint64_t)(uintptr_t)encap_decap->action;
   10262                 :            :                                 type = DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT;
   10263                 :          0 :                                 save_dump_file(data, size, type,
   10264                 :            :                                         id, NULL, file);
   10265                 :          0 :                                 e = LIST_NEXT(e, next);
   10266                 :            :                         }
   10267                 :            :                 }
   10268                 :            :         }
   10269                 :            : 
   10270                 :            :         /* get modify_hdr */
   10271                 :          0 :         h = sh->modify_cmds;
   10272         [ #  # ]:          0 :         if (h) {
   10273                 :          0 :                 lcore_index = rte_lcore_index(rte_lcore_id());
   10274         [ #  # ]:          0 :                 if (unlikely(lcore_index == -1)) {
   10275                 :            :                         lcore_index = MLX5_LIST_NLCORE;
   10276                 :          0 :                         rte_spinlock_lock(&h->l_const.lcore_lock);
   10277                 :            :                 }
   10278                 :          0 :                 i = lcore_index;
   10279                 :            : 
   10280         [ #  # ]:          0 :                 if (lcore_index == MLX5_LIST_NLCORE) {
   10281         [ #  # ]:          0 :                         for (i = 0; i <= (uint32_t)lcore_index; i++) {
   10282         [ #  # ]:          0 :                                 for (j = 0; j <= h->mask; j++) {
   10283                 :            :                                         l_inconst = &h->buckets[j].l;
   10284         [ #  # ]:          0 :                                         if (!l_inconst || !l_inconst->cache[i])
   10285                 :          0 :                                                 continue;
   10286                 :            : 
   10287                 :          0 :                                         e = LIST_FIRST(&l_inconst->cache[i]->h);
   10288         [ #  # ]:          0 :                                         while (e) {
   10289                 :            :                                                 modify_hdr =
   10290                 :            :                                                 (struct mlx5_flow_dv_modify_hdr_resource *)e;
   10291                 :          0 :                                                 data = (const uint8_t *)modify_hdr->actions;
   10292                 :          0 :                                                 size = (size_t)(modify_hdr->actions_num) * 8;
   10293                 :          0 :                                                 actions_num = modify_hdr->actions_num;
   10294                 :          0 :                                                 id = (uint64_t)(uintptr_t)modify_hdr->action;
   10295                 :            :                                                 type = DR_DUMP_REC_TYPE_PMD_MODIFY_HDR;
   10296                 :          0 :                                                 save_dump_file(data, size, type, id,
   10297                 :            :                                                                 (void *)(&actions_num), file);
   10298                 :          0 :                                                 e = LIST_NEXT(e, next);
   10299                 :            :                                         }
   10300                 :            :                                 }
   10301                 :            :                         }
   10302                 :            :                 } else {
   10303         [ #  # ]:          0 :                         for (j = 0; j <= h->mask; j++) {
   10304                 :            :                                 l_inconst = &h->buckets[j].l;
   10305         [ #  # ]:          0 :                                 if (!l_inconst || !l_inconst->cache[i])
   10306                 :          0 :                                         continue;
   10307                 :            : 
   10308                 :          0 :                                 e = LIST_FIRST(&l_inconst->cache[i]->h);
   10309         [ #  # ]:          0 :                                 while (e) {
   10310                 :            :                                         modify_hdr =
   10311                 :            :                                         (struct mlx5_flow_dv_modify_hdr_resource *)e;
   10312                 :          0 :                                         data = (const uint8_t *)modify_hdr->actions;
   10313                 :          0 :                                         size = (size_t)(modify_hdr->actions_num) * 8;
   10314                 :          0 :                                         actions_num = modify_hdr->actions_num;
   10315                 :          0 :                                         id = (uint64_t)(uintptr_t)modify_hdr->action;
   10316                 :            :                                         type = DR_DUMP_REC_TYPE_PMD_MODIFY_HDR;
   10317                 :          0 :                                         save_dump_file(data, size, type, id,
   10318                 :            :                                                         (void *)(&actions_num), file);
   10319                 :          0 :                                         e = LIST_NEXT(e, next);
   10320                 :            :                                 }
   10321                 :            :                         }
   10322                 :            :                 }
   10323                 :            : 
   10324         [ #  # ]:          0 :                 if (unlikely(lcore_index == MLX5_LIST_NLCORE))
   10325                 :          0 :                         rte_spinlock_unlock(&h->l_const.lcore_lock);
   10326                 :            :         }
   10327                 :            : 
   10328                 :            :         /* get counter */
   10329                 :            :         MLX5_ASSERT(cmng->n_valid <= MLX5_COUNTER_POOLS_MAX_NUM);
   10330                 :          0 :         max = MLX5_COUNTERS_PER_POOL * cmng->n_valid;
   10331         [ #  # ]:          0 :         for (j = 1; j <= max; j++) {
   10332                 :          0 :                 action = NULL;
   10333         [ #  # ]:          0 :                 if ((!mlx5_counter_query(dev, j, false, &count.hits,
   10334         [ #  # ]:          0 :                 &count.bytes, &action)) && action) {
   10335                 :          0 :                         id = (uint64_t)(uintptr_t)action;
   10336                 :            :                         type = DR_DUMP_REC_TYPE_PMD_COUNTER;
   10337                 :          0 :                         save_dump_file(NULL, 0, type,
   10338                 :            :                                         id, (void *)&count, file);
   10339                 :            :                 }
   10340                 :            :         }
   10341                 :          0 :         return 0;
   10342                 :            : }
   10343                 :            : #endif
   10344                 :            : 
   10345                 :            : /**
   10346                 :            :  * Dump flow raw hw data to file
   10347                 :            :  *
   10348                 :            :  * @param[in] dev
   10349                 :            :  *    The pointer to Ethernet device.
   10350                 :            :  * @param[in] file
   10351                 :            :  *   A pointer to a file for output.
   10352                 :            :  * @param[out] error
   10353                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
   10354                 :            :  *   structure in case of error only.
   10355                 :            :  * @return
   10356                 :            :  *   0 on success, a negative value otherwise.
   10357                 :            :  */
   10358                 :            : int
   10359                 :          0 : mlx5_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow_idx,
   10360                 :            :                    FILE *file,
   10361                 :            :                    struct rte_flow_error *error __rte_unused)
   10362                 :            : {
   10363                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10364                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   10365                 :            :         uint32_t handle_idx;
   10366                 :            :         int ret;
   10367                 :            :         struct mlx5_flow_handle *dh;
   10368                 :            :         struct rte_flow *flow;
   10369                 :            : 
   10370         [ #  # ]:          0 :         if (!sh->config.dv_flow_en) {
   10371         [ #  # ]:          0 :                 if (fputs("device dv flow disabled\n", file) <= 0)
   10372                 :          0 :                         return -errno;
   10373                 :            :                 return -ENOTSUP;
   10374                 :            :         }
   10375                 :            : 
   10376                 :            :         /* dump all */
   10377         [ #  # ]:          0 :         if (!flow_idx) {
   10378                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
   10379         [ #  # ]:          0 :                 if (mlx5_flow_dev_dump_sh_all(dev, file, error))
   10380                 :            :                         return -EINVAL;
   10381                 :            : 
   10382         [ #  # ]:          0 :                 if (sh->config.dv_flow_en == 2)
   10383                 :          0 :                         return mlx5dr_debug_dump(priv->dr_ctx, file);
   10384                 :            : #endif
   10385                 :          0 :                 return mlx5_devx_cmd_flow_dump(sh->fdb_domain,
   10386                 :            :                                                sh->rx_domain,
   10387                 :            :                                                sh->tx_domain, file);
   10388                 :            :         }
   10389                 :            :         /* dump one */
   10390                 :          0 :         flow = mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN],
   10391                 :            :                         (uintptr_t)(void *)flow_idx);
   10392         [ #  # ]:          0 :         if (!flow)
   10393                 :            :                 return -EINVAL;
   10394                 :            : 
   10395                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
   10396                 :          0 :         mlx5_flow_dev_dump_ipool(dev, flow, file, error);
   10397                 :            : #endif
   10398                 :          0 :         handle_idx = flow->dev_handles;
   10399         [ #  # ]:          0 :         while (handle_idx) {
   10400                 :          0 :                 dh = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   10401                 :            :                                 handle_idx);
   10402         [ #  # ]:          0 :                 if (!dh)
   10403                 :            :                         return -ENOENT;
   10404         [ #  # ]:          0 :                 if (dh->drv_flow) {
   10405         [ #  # ]:          0 :                         if (sh->config.dv_flow_en == 2)
   10406                 :            :                                 return -ENOTSUP;
   10407                 :            : 
   10408                 :          0 :                         ret = mlx5_devx_cmd_flow_single_dump(dh->drv_flow,
   10409                 :            :                                                              file);
   10410         [ #  # ]:          0 :                         if (ret)
   10411                 :            :                                 return -ENOENT;
   10412                 :            :                 }
   10413                 :          0 :                 handle_idx = dh->next.next;
   10414                 :            :         }
   10415                 :            :         return 0;
   10416                 :            : }
   10417                 :            : 
   10418                 :            : /**
   10419                 :            :  * Get aged-out flows.
   10420                 :            :  *
   10421                 :            :  * @param[in] dev
   10422                 :            :  *   Pointer to the Ethernet device structure.
   10423                 :            :  * @param[in] context
   10424                 :            :  *   The address of an array of pointers to the aged-out flows contexts.
   10425                 :            :  * @param[in] nb_countexts
   10426                 :            :  *   The length of context array pointers.
   10427                 :            :  * @param[out] error
   10428                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   10429                 :            :  *   error only.
   10430                 :            :  *
   10431                 :            :  * @return
   10432                 :            :  *   how many contexts get in success, otherwise negative errno value.
   10433                 :            :  *   if nb_contexts is 0, return the amount of all aged contexts.
   10434                 :            :  *   if nb_contexts is not 0 , return the amount of aged flows reported
   10435                 :            :  *   in the context array.
   10436                 :            :  */
   10437                 :            : int
   10438         [ #  # ]:          0 : mlx5_flow_get_aged_flows(struct rte_eth_dev *dev, void **contexts,
   10439                 :            :                         uint32_t nb_contexts, struct rte_flow_error *error)
   10440                 :            : {
   10441                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   10442                 :            : 
   10443                 :          0 :         return flow_get_drv_ops(flow_get_drv_type(dev, &attr))->get_aged_flows
   10444                 :            :                 (dev, contexts, nb_contexts, error);
   10445                 :            : }
   10446                 :            : 
   10447                 :            : /**
   10448                 :            :  * Get aged-out flows per HWS queue.
   10449                 :            :  *
   10450                 :            :  * @param[in] dev
   10451                 :            :  *   Pointer to the Ethernet device structure.
   10452                 :            :  * @param[in] queue_id
   10453                 :            :  *   Flow queue to query.
   10454                 :            :  * @param[in] context
   10455                 :            :  *   The address of an array of pointers to the aged-out flows contexts.
   10456                 :            :  * @param[in] nb_countexts
   10457                 :            :  *   The length of context array pointers.
   10458                 :            :  * @param[out] error
   10459                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   10460                 :            :  *   error only.
   10461                 :            :  *
   10462                 :            :  * @return
   10463                 :            :  *   how many contexts get in success, otherwise negative errno value.
   10464                 :            :  *   if nb_contexts is 0, return the amount of all aged contexts.
   10465                 :            :  *   if nb_contexts is not 0 , return the amount of aged flows reported
   10466                 :            :  *   in the context array.
   10467                 :            :  */
   10468                 :            : int
   10469         [ #  # ]:          0 : mlx5_flow_get_q_aged_flows(struct rte_eth_dev *dev, uint32_t queue_id,
   10470                 :            :                            void **contexts, uint32_t nb_contexts,
   10471                 :            :                            struct rte_flow_error *error)
   10472                 :            : {
   10473                 :            :         const struct mlx5_flow_driver_ops *fops;
   10474                 :            :         struct rte_flow_attr attr = { 0 };
   10475                 :            : 
   10476                 :            :         if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_HW) {
   10477                 :          0 :                 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW);
   10478                 :          0 :                 return fops->get_q_aged_flows(dev, queue_id, contexts,
   10479                 :            :                                               nb_contexts, error);
   10480                 :            :         }
   10481                 :          0 :         DRV_LOG(ERR, "port %u queue %u get aged flows is not supported.",
   10482                 :            :                 dev->data->port_id, queue_id);
   10483                 :          0 :         return rte_flow_error_set(error, ENOTSUP,
   10484                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10485                 :            :                                   "get Q aged flows with incorrect steering mode");
   10486                 :            : }
   10487                 :            : 
   10488                 :            : /* Wrapper for driver action_validate op callback */
   10489                 :            : static int
   10490                 :          0 : flow_drv_action_validate(struct rte_eth_dev *dev,
   10491                 :            :                          const struct rte_flow_indir_action_conf *conf,
   10492                 :            :                          const struct rte_flow_action *action,
   10493                 :            :                          const struct mlx5_flow_driver_ops *fops,
   10494                 :            :                          struct rte_flow_error *error)
   10495                 :            : {
   10496                 :            :         static const char err_msg[] = "indirect action validation unsupported";
   10497                 :            : 
   10498         [ #  # ]:          0 :         if (!fops->action_validate) {
   10499                 :          0 :                 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg);
   10500                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   10501                 :            :                                    NULL, err_msg);
   10502                 :          0 :                 return -rte_errno;
   10503                 :            :         }
   10504                 :          0 :         return fops->action_validate(dev, conf, action, error);
   10505                 :            : }
   10506                 :            : 
   10507                 :            : /**
   10508                 :            :  * Destroys the shared action by handle.
   10509                 :            :  *
   10510                 :            :  * @param dev
   10511                 :            :  *   Pointer to Ethernet device structure.
   10512                 :            :  * @param[in] handle
   10513                 :            :  *   Handle for the indirect action object to be destroyed.
   10514                 :            :  * @param[out] error
   10515                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
   10516                 :            :  *   structure in case of error only.
   10517                 :            :  *
   10518                 :            :  * @return
   10519                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   10520                 :            :  *
   10521                 :            :  * @note: wrapper for driver action_create op callback.
   10522                 :            :  */
   10523                 :            : static int
   10524         [ #  # ]:          0 : mlx5_action_handle_destroy(struct rte_eth_dev *dev,
   10525                 :            :                            struct rte_flow_action_handle *handle,
   10526                 :            :                            struct rte_flow_error *error)
   10527                 :            : {
   10528                 :            :         static const char err_msg[] = "indirect action destruction unsupported";
   10529                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   10530                 :          0 :         const struct mlx5_flow_driver_ops *fops =
   10531                 :            :                         flow_get_drv_ops(flow_get_drv_type(dev, &attr));
   10532                 :            : 
   10533         [ #  # ]:          0 :         if (!fops->action_destroy) {
   10534                 :          0 :                 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg);
   10535                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   10536                 :            :                                    NULL, err_msg);
   10537                 :          0 :                 return -rte_errno;
   10538                 :            :         }
   10539                 :          0 :         return fops->action_destroy(dev, handle, error);
   10540                 :            : }
   10541                 :            : 
   10542                 :            : /* Wrapper for driver action_destroy op callback */
   10543                 :            : static int
   10544                 :          0 : flow_drv_action_update(struct rte_eth_dev *dev,
   10545                 :            :                        struct rte_flow_action_handle *handle,
   10546                 :            :                        const void *update,
   10547                 :            :                        const struct mlx5_flow_driver_ops *fops,
   10548                 :            :                        struct rte_flow_error *error)
   10549                 :            : {
   10550                 :            :         static const char err_msg[] = "indirect action update unsupported";
   10551                 :            : 
   10552         [ #  # ]:          0 :         if (!fops->action_update) {
   10553                 :          0 :                 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg);
   10554                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   10555                 :            :                                    NULL, err_msg);
   10556                 :          0 :                 return -rte_errno;
   10557                 :            :         }
   10558                 :          0 :         return fops->action_update(dev, handle, update, error);
   10559                 :            : }
   10560                 :            : 
   10561                 :            : /* Wrapper for driver action_destroy op callback */
   10562                 :            : static int
   10563                 :          0 : flow_drv_action_query(struct rte_eth_dev *dev,
   10564                 :            :                       const struct rte_flow_action_handle *handle,
   10565                 :            :                       void *data,
   10566                 :            :                       const struct mlx5_flow_driver_ops *fops,
   10567                 :            :                       struct rte_flow_error *error)
   10568                 :            : {
   10569                 :            :         static const char err_msg[] = "indirect action query unsupported";
   10570                 :            : 
   10571         [ #  # ]:          0 :         if (!fops->action_query) {
   10572                 :          0 :                 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg);
   10573                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   10574                 :            :                                    NULL, err_msg);
   10575                 :          0 :                 return -rte_errno;
   10576                 :            :         }
   10577                 :          0 :         return fops->action_query(dev, handle, data, error);
   10578                 :            : }
   10579                 :            : 
   10580                 :            : /**
   10581                 :            :  * Create indirect action for reuse in multiple flow rules.
   10582                 :            :  *
   10583                 :            :  * @param dev
   10584                 :            :  *   Pointer to Ethernet device structure.
   10585                 :            :  * @param conf
   10586                 :            :  *   Pointer to indirect action object configuration.
   10587                 :            :  * @param[in] action
   10588                 :            :  *   Action configuration for indirect action object creation.
   10589                 :            :  * @param[out] error
   10590                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
   10591                 :            :  *   structure in case of error only.
   10592                 :            :  * @return
   10593                 :            :  *   A valid handle in case of success, NULL otherwise and rte_errno is set.
   10594                 :            :  */
   10595                 :            : static struct rte_flow_action_handle *
   10596         [ #  # ]:          0 : mlx5_action_handle_create(struct rte_eth_dev *dev,
   10597                 :            :                           const struct rte_flow_indir_action_conf *conf,
   10598                 :            :                           const struct rte_flow_action *action,
   10599                 :            :                           struct rte_flow_error *error)
   10600                 :            : {
   10601                 :            :         static const char err_msg[] = "indirect action creation unsupported";
   10602                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   10603                 :          0 :         const struct mlx5_flow_driver_ops *fops =
   10604                 :            :                         flow_get_drv_ops(flow_get_drv_type(dev, &attr));
   10605                 :            : 
   10606         [ #  # ]:          0 :         if (flow_drv_action_validate(dev, conf, action, fops, error))
   10607                 :            :                 return NULL;
   10608         [ #  # ]:          0 :         if (!fops->action_create) {
   10609                 :          0 :                 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg);
   10610                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   10611                 :            :                                    NULL, err_msg);
   10612                 :          0 :                 return NULL;
   10613                 :            :         }
   10614                 :          0 :         return fops->action_create(dev, conf, action, error);
   10615                 :            : }
   10616                 :            : 
   10617                 :            : /**
   10618                 :            :  * Updates inplace the indirect action configuration pointed by *handle*
   10619                 :            :  * with the configuration provided as *update* argument.
   10620                 :            :  * The update of the indirect action configuration effects all flow rules
   10621                 :            :  * reusing the action via handle.
   10622                 :            :  *
   10623                 :            :  * @param dev
   10624                 :            :  *   Pointer to Ethernet device structure.
   10625                 :            :  * @param[in] handle
   10626                 :            :  *   Handle for the indirect action to be updated.
   10627                 :            :  * @param[in] update
   10628                 :            :  *   Action specification used to modify the action pointed by handle.
   10629                 :            :  *   *update* could be of same type with the action pointed by the *handle*
   10630                 :            :  *   handle argument, or some other structures like a wrapper, depending on
   10631                 :            :  *   the indirect action type.
   10632                 :            :  * @param[out] error
   10633                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
   10634                 :            :  *   structure in case of error only.
   10635                 :            :  *
   10636                 :            :  * @return
   10637                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   10638                 :            :  */
   10639                 :            : static int
   10640         [ #  # ]:          0 : mlx5_action_handle_update(struct rte_eth_dev *dev,
   10641                 :            :                 struct rte_flow_action_handle *handle,
   10642                 :            :                 const void *update,
   10643                 :            :                 struct rte_flow_error *error)
   10644                 :            : {
   10645                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   10646                 :          0 :         const struct mlx5_flow_driver_ops *fops =
   10647                 :            :                         flow_get_drv_ops(flow_get_drv_type(dev, &attr));
   10648                 :            :         int ret;
   10649                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   10650                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   10651                 :            : 
   10652         [ #  # ]:          0 :         switch (type) {
   10653                 :            :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   10654                 :            :         case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
   10655                 :            :                 ret = 0;
   10656                 :            :                 break;
   10657                 :          0 :         default:
   10658                 :          0 :                 ret = flow_drv_action_validate(dev, NULL,
   10659                 :            :                                 (const struct rte_flow_action *)update,
   10660                 :            :                                 fops, error);
   10661                 :            :         }
   10662         [ #  # ]:          0 :         if (ret)
   10663                 :            :                 return ret;
   10664                 :          0 :         return flow_drv_action_update(dev, handle, update, fops,
   10665                 :            :                                       error);
   10666                 :            : }
   10667                 :            : 
   10668                 :            : /**
   10669                 :            :  * Query the indirect action by handle.
   10670                 :            :  *
   10671                 :            :  * This function allows retrieving action-specific data such as counters.
   10672                 :            :  * Data is gathered by special action which may be present/referenced in
   10673                 :            :  * more than one flow rule definition.
   10674                 :            :  *
   10675                 :            :  * see @RTE_FLOW_ACTION_TYPE_COUNT
   10676                 :            :  *
   10677                 :            :  * @param dev
   10678                 :            :  *   Pointer to Ethernet device structure.
   10679                 :            :  * @param[in] handle
   10680                 :            :  *   Handle for the indirect action to query.
   10681                 :            :  * @param[in, out] data
   10682                 :            :  *   Pointer to storage for the associated query data type.
   10683                 :            :  * @param[out] error
   10684                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
   10685                 :            :  *   structure in case of error only.
   10686                 :            :  *
   10687                 :            :  * @return
   10688                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   10689                 :            :  */
   10690                 :            : static int
   10691         [ #  # ]:          0 : mlx5_action_handle_query(struct rte_eth_dev *dev,
   10692                 :            :                          const struct rte_flow_action_handle *handle,
   10693                 :            :                          void *data,
   10694                 :            :                          struct rte_flow_error *error)
   10695                 :            : {
   10696                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   10697                 :          0 :         const struct mlx5_flow_driver_ops *fops =
   10698                 :            :                         flow_get_drv_ops(flow_get_drv_type(dev, &attr));
   10699                 :            : 
   10700                 :          0 :         return flow_drv_action_query(dev, handle, data, fops, error);
   10701                 :            : }
   10702                 :            : 
   10703                 :            : static int
   10704         [ #  # ]:          0 : mlx5_action_handle_query_update(struct rte_eth_dev *dev,
   10705                 :            :                                 struct rte_flow_action_handle *handle,
   10706                 :            :                                 const void *update, void *query,
   10707                 :            :                                 enum rte_flow_query_update_mode qu_mode,
   10708                 :            :                                 struct rte_flow_error *error)
   10709                 :            : {
   10710                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   10711                 :            :         enum mlx5_flow_drv_type drv_type = flow_get_drv_type(dev, &attr);
   10712                 :            :         const struct mlx5_flow_driver_ops *fops;
   10713                 :            : 
   10714                 :            :         if (drv_type == MLX5_FLOW_TYPE_MIN || drv_type == MLX5_FLOW_TYPE_MAX)
   10715                 :            :                 return rte_flow_error_set(error, ENOTSUP,
   10716                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   10717                 :            :                                           NULL, "invalid driver type");
   10718                 :          0 :         fops = flow_get_drv_ops(drv_type);
   10719   [ #  #  #  # ]:          0 :         if (!fops || !fops->action_query_update)
   10720                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   10721                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   10722                 :            :                                           NULL, "no query_update handler");
   10723                 :          0 :         return fops->action_query_update(dev, handle, update,
   10724                 :            :                                          query, qu_mode, error);
   10725                 :            : }
   10726                 :            : 
   10727                 :            : 
   10728                 :            : #define MLX5_DRV_FOPS_OR_ERR(dev, fops, drv_cb, ret)                           \
   10729                 :            : {                                                                              \
   10730                 :            :         struct rte_flow_attr attr = { .transfer = 0 };                         \
   10731                 :            :         enum mlx5_flow_drv_type drv_type = flow_get_drv_type((dev), &attr);    \
   10732                 :            :         if (drv_type == MLX5_FLOW_TYPE_MIN ||                                  \
   10733                 :            :             drv_type == MLX5_FLOW_TYPE_MAX) {                                  \
   10734                 :            :                 rte_flow_error_set(error, ENOTSUP,                             \
   10735                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION,                 \
   10736                 :            :                                    NULL, "invalid driver type");               \
   10737                 :            :                 return ret;                                                    \
   10738                 :            :         }                                                                      \
   10739                 :            :         (fops) = flow_get_drv_ops(drv_type);                                   \
   10740                 :            :         if (!(fops) || !(fops)->drv_cb) {                                      \
   10741                 :            :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, \
   10742                 :            :                                    NULL, "no action_list handler");            \
   10743                 :            :                 return ret;                                                    \
   10744                 :            :         }                                                                      \
   10745                 :            : }
   10746                 :            : 
   10747                 :            : static struct rte_flow_action_list_handle *
   10748         [ #  # ]:          0 : mlx5_action_list_handle_create(struct rte_eth_dev *dev,
   10749                 :            :                                const struct rte_flow_indir_action_conf *conf,
   10750                 :            :                                const struct rte_flow_action *actions,
   10751                 :            :                                struct rte_flow_error *error)
   10752                 :            : {
   10753                 :            :         const struct mlx5_flow_driver_ops *fops;
   10754                 :            : 
   10755   [ #  #  #  # ]:          0 :         MLX5_DRV_FOPS_OR_ERR(dev, fops, action_list_handle_create, NULL);
   10756                 :          0 :         return fops->action_list_handle_create(dev, conf, actions, error);
   10757                 :            : }
   10758                 :            : 
   10759                 :            : static int
   10760         [ #  # ]:          0 : mlx5_action_list_handle_destroy(struct rte_eth_dev *dev,
   10761                 :            :                                 struct rte_flow_action_list_handle *handle,
   10762                 :            :                                 struct rte_flow_error *error)
   10763                 :            : {
   10764                 :            :         const struct mlx5_flow_driver_ops *fops;
   10765                 :            : 
   10766   [ #  #  #  # ]:          0 :         MLX5_DRV_FOPS_OR_ERR(dev, fops, action_list_handle_destroy, ENOTSUP);
   10767                 :          0 :         return fops->action_list_handle_destroy(dev, handle, error);
   10768                 :            : }
   10769                 :            : 
   10770                 :            : static int
   10771         [ #  # ]:          0 : mlx5_flow_action_list_handle_query_update(struct rte_eth_dev *dev,
   10772                 :            :                                           const
   10773                 :            :                                           struct rte_flow_action_list_handle *handle,
   10774                 :            :                                           const void **update, void **query,
   10775                 :            :                                           enum rte_flow_query_update_mode mode,
   10776                 :            :                                           struct rte_flow_error *error)
   10777                 :            : {
   10778                 :            :         const struct mlx5_flow_driver_ops *fops;
   10779                 :            : 
   10780   [ #  #  #  # ]:          0 :         MLX5_DRV_FOPS_OR_ERR(dev, fops,
   10781                 :            :                              action_list_handle_query_update, ENOTSUP);
   10782                 :          0 :         return fops->action_list_handle_query_update(dev, handle, update, query,
   10783                 :            :                                                      mode, error);
   10784                 :            : }
   10785                 :            : static int
   10786         [ #  # ]:          0 : mlx5_flow_calc_table_hash(struct rte_eth_dev *dev,
   10787                 :            :                           const struct rte_flow_template_table *table,
   10788                 :            :                           const struct rte_flow_item pattern[],
   10789                 :            :                           uint8_t pattern_template_index,
   10790                 :            :                           uint32_t *hash, struct rte_flow_error *error)
   10791                 :            : {
   10792                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   10793                 :            :         enum mlx5_flow_drv_type drv_type = flow_get_drv_type(dev, &attr);
   10794                 :            :         const struct mlx5_flow_driver_ops *fops;
   10795                 :            : 
   10796                 :            :         if (drv_type == MLX5_FLOW_TYPE_MIN || drv_type == MLX5_FLOW_TYPE_MAX)
   10797                 :            :                 return rte_flow_error_set(error, ENOTSUP,
   10798                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   10799                 :            :                                           NULL, "invalid driver type");
   10800                 :          0 :         fops = flow_get_drv_ops(drv_type);
   10801   [ #  #  #  # ]:          0 :         if (!fops || !fops->action_query_update)
   10802                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   10803                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   10804                 :            :                                           NULL, "no query_update handler");
   10805                 :          0 :         return fops->flow_calc_table_hash(dev, table, pattern, pattern_template_index,
   10806                 :            :                                           hash, error);
   10807                 :            : }
   10808                 :            : 
   10809                 :            : static int
   10810         [ #  # ]:          0 : mlx5_flow_calc_encap_hash(struct rte_eth_dev *dev,
   10811                 :            :                           const struct rte_flow_item pattern[],
   10812                 :            :                           enum rte_flow_encap_hash_field dest_field,
   10813                 :            :                           uint8_t *hash,
   10814                 :            :                           struct rte_flow_error *error)
   10815                 :            : {
   10816                 :            :         enum mlx5_flow_drv_type drv_type = flow_get_drv_type(dev, NULL);
   10817                 :            :         const struct mlx5_flow_driver_ops *fops;
   10818                 :            : 
   10819                 :            :         if (drv_type == MLX5_FLOW_TYPE_MIN || drv_type == MLX5_FLOW_TYPE_MAX)
   10820                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   10821                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   10822                 :            :                                           NULL, "invalid driver type");
   10823                 :          0 :         fops = flow_get_drv_ops(drv_type);
   10824   [ #  #  #  # ]:          0 :         if (!fops || !fops->flow_calc_encap_hash)
   10825                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   10826                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   10827                 :            :                                           NULL, "no calc encap hash handler");
   10828                 :          0 :         return fops->flow_calc_encap_hash(dev, pattern, dest_field, hash, error);
   10829                 :            : }
   10830                 :            : 
   10831                 :            : static int
   10832         [ #  # ]:          0 : mlx5_template_table_resize(struct rte_eth_dev *dev,
   10833                 :            :                            struct rte_flow_template_table *table,
   10834                 :            :                            uint32_t nb_rules, struct rte_flow_error *error)
   10835                 :            : {
   10836                 :            :         const struct mlx5_flow_driver_ops *fops;
   10837                 :            : 
   10838   [ #  #  #  # ]:          0 :         MLX5_DRV_FOPS_OR_ERR(dev, fops, table_resize, ENOTSUP);
   10839                 :          0 :         return fops->table_resize(dev, table, nb_rules, error);
   10840                 :            : }
   10841                 :            : 
   10842                 :            : static int
   10843         [ #  # ]:          0 : mlx5_table_resize_complete(struct rte_eth_dev *dev,
   10844                 :            :                            struct rte_flow_template_table *table,
   10845                 :            :                            struct rte_flow_error *error)
   10846                 :            : {
   10847                 :            :         const struct mlx5_flow_driver_ops *fops;
   10848                 :            : 
   10849   [ #  #  #  # ]:          0 :         MLX5_DRV_FOPS_OR_ERR(dev, fops, table_resize_complete, ENOTSUP);
   10850                 :          0 :         return fops->table_resize_complete(dev, table, error);
   10851                 :            : }
   10852                 :            : 
   10853                 :            : static int
   10854         [ #  # ]:          0 : mlx5_flow_async_update_resized(struct rte_eth_dev *dev, uint32_t queue,
   10855                 :            :                                const struct rte_flow_op_attr *op_attr,
   10856                 :            :                                struct rte_flow *rule, void *user_data,
   10857                 :            :                                struct rte_flow_error *error)
   10858                 :            : {
   10859                 :            :         const struct mlx5_flow_driver_ops *fops;
   10860                 :            : 
   10861   [ #  #  #  # ]:          0 :         MLX5_DRV_FOPS_OR_ERR(dev, fops, flow_update_resized, ENOTSUP);
   10862                 :          0 :         return fops->flow_update_resized(dev, queue, op_attr, rule, user_data, error);
   10863                 :            : }
   10864                 :            : 
   10865                 :            : /**
   10866                 :            :  * Destroy all indirect actions (shared RSS).
   10867                 :            :  *
   10868                 :            :  * @param dev
   10869                 :            :  *   Pointer to Ethernet device.
   10870                 :            :  *
   10871                 :            :  * @return
   10872                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   10873                 :            :  */
   10874                 :            : int
   10875                 :          0 : mlx5_action_handle_flush(struct rte_eth_dev *dev)
   10876                 :            : {
   10877                 :            :         struct rte_flow_error error;
   10878                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10879                 :            :         struct mlx5_shared_action_rss *shared_rss;
   10880                 :            :         int ret = 0;
   10881                 :            :         uint32_t idx;
   10882                 :            : 
   10883   [ #  #  #  # ]:          0 :         ILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   10884                 :            :                       priv->rss_shared_actions, idx, shared_rss, next) {
   10885         [ #  # ]:          0 :                 ret |= mlx5_action_handle_destroy(dev,
   10886                 :          0 :                        (struct rte_flow_action_handle *)(uintptr_t)idx, &error);
   10887                 :            :         }
   10888                 :          0 :         return ret;
   10889                 :            : }
   10890                 :            : 
   10891                 :            : /**
   10892                 :            :  * Validate existing indirect actions against current device configuration
   10893                 :            :  * and attach them to device resources.
   10894                 :            :  *
   10895                 :            :  * @param dev
   10896                 :            :  *   Pointer to Ethernet device.
   10897                 :            :  *
   10898                 :            :  * @return
   10899                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   10900                 :            :  */
   10901                 :            : int
   10902                 :          0 : mlx5_action_handle_attach(struct rte_eth_dev *dev)
   10903                 :            : {
   10904                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10905                 :            :         int ret = 0;
   10906                 :            :         struct mlx5_ind_table_obj *ind_tbl, *ind_tbl_last;
   10907                 :            : 
   10908         [ #  # ]:          0 :         LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) {
   10909                 :            :                 const char *message;
   10910                 :            :                 uint32_t queue_idx;
   10911                 :            : 
   10912                 :          0 :                 ret = mlx5_validate_rss_queues(dev, ind_tbl->queues,
   10913                 :            :                                                ind_tbl->queues_n,
   10914                 :            :                                                &message, &queue_idx);
   10915         [ #  # ]:          0 :                 if (ret != 0) {
   10916                 :          0 :                         DRV_LOG(ERR, "Port %u cannot use queue %u in RSS: %s",
   10917                 :            :                                 dev->data->port_id, ind_tbl->queues[queue_idx],
   10918                 :            :                                 message);
   10919                 :          0 :                         break;
   10920                 :            :                 }
   10921                 :            :         }
   10922         [ #  # ]:          0 :         if (ret != 0)
   10923                 :            :                 return ret;
   10924         [ #  # ]:          0 :         LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) {
   10925                 :          0 :                 ret = mlx5_ind_table_obj_attach(dev, ind_tbl);
   10926         [ #  # ]:          0 :                 if (ret != 0) {
   10927                 :          0 :                         DRV_LOG(ERR, "Port %u could not attach "
   10928                 :            :                                 "indirection table obj %p",
   10929                 :            :                                 dev->data->port_id, (void *)ind_tbl);
   10930                 :          0 :                         goto error;
   10931                 :            :                 }
   10932                 :            :         }
   10933                 :            : 
   10934                 :            :         return 0;
   10935                 :            : error:
   10936                 :            :         ind_tbl_last = ind_tbl;
   10937         [ #  # ]:          0 :         LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) {
   10938         [ #  # ]:          0 :                 if (ind_tbl == ind_tbl_last)
   10939                 :            :                         break;
   10940         [ #  # ]:          0 :                 if (mlx5_ind_table_obj_detach(dev, ind_tbl) != 0)
   10941                 :          0 :                         DRV_LOG(CRIT, "Port %u could not detach "
   10942                 :            :                                 "indirection table obj %p on rollback",
   10943                 :            :                                 dev->data->port_id, (void *)ind_tbl);
   10944                 :            :         }
   10945                 :            :         return ret;
   10946                 :            : }
   10947                 :            : 
   10948                 :            : /**
   10949                 :            :  * Detach indirect actions of the device from its resources.
   10950                 :            :  *
   10951                 :            :  * @param dev
   10952                 :            :  *   Pointer to Ethernet device.
   10953                 :            :  *
   10954                 :            :  * @return
   10955                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   10956                 :            :  */
   10957                 :            : int
   10958                 :          0 : mlx5_action_handle_detach(struct rte_eth_dev *dev)
   10959                 :            : {
   10960                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10961                 :            :         int ret = 0;
   10962                 :            :         struct mlx5_ind_table_obj *ind_tbl, *ind_tbl_last;
   10963                 :            : 
   10964         [ #  # ]:          0 :         LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) {
   10965                 :          0 :                 ret = mlx5_ind_table_obj_detach(dev, ind_tbl);
   10966         [ #  # ]:          0 :                 if (ret != 0) {
   10967                 :          0 :                         DRV_LOG(ERR, "Port %u could not detach "
   10968                 :            :                                 "indirection table obj %p",
   10969                 :            :                                 dev->data->port_id, (void *)ind_tbl);
   10970                 :          0 :                         goto error;
   10971                 :            :                 }
   10972                 :            :         }
   10973                 :            :         return 0;
   10974                 :            : error:
   10975                 :            :         ind_tbl_last = ind_tbl;
   10976         [ #  # ]:          0 :         LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) {
   10977         [ #  # ]:          0 :                 if (ind_tbl == ind_tbl_last)
   10978                 :            :                         break;
   10979         [ #  # ]:          0 :                 if (mlx5_ind_table_obj_attach(dev, ind_tbl) != 0)
   10980                 :          0 :                         DRV_LOG(CRIT, "Port %u could not attach "
   10981                 :            :                                 "indirection table obj %p on rollback",
   10982                 :            :                                 dev->data->port_id, (void *)ind_tbl);
   10983                 :            :         }
   10984                 :            :         return ret;
   10985                 :            : }
   10986                 :            : 
   10987                 :            : #ifndef HAVE_MLX5DV_DR
   10988                 :            : #define MLX5_DOMAIN_SYNC_FLOW ((1 << 0) | (1 << 1))
   10989                 :            : #else
   10990                 :            : #define MLX5_DOMAIN_SYNC_FLOW \
   10991                 :            :         (MLX5DV_DR_DOMAIN_SYNC_FLAGS_SW | MLX5DV_DR_DOMAIN_SYNC_FLAGS_HW)
   10992                 :            : #endif
   10993                 :            : 
   10994                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_sync_flow, 20.11)
   10995                 :          0 : int rte_pmd_mlx5_sync_flow(uint16_t port_id, uint32_t domains)
   10996                 :            : {
   10997         [ #  # ]:          0 :         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
   10998                 :            :         const struct mlx5_flow_driver_ops *fops;
   10999                 :            :         int ret;
   11000                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   11001                 :            : 
   11002                 :          0 :         fops = flow_get_drv_ops(flow_get_drv_type(dev, &attr));
   11003                 :          0 :         ret = fops->sync_domain(dev, domains, MLX5_DOMAIN_SYNC_FLOW);
   11004         [ #  # ]:          0 :         if (ret > 0)
   11005                 :          0 :                 ret = -ret;
   11006                 :          0 :         return ret;
   11007                 :            : }
   11008                 :            : 
   11009                 :            : const struct mlx5_flow_tunnel *
   11010                 :          0 : mlx5_get_tof(const struct rte_flow_item *item,
   11011                 :            :              const struct rte_flow_action *action,
   11012                 :            :              enum mlx5_tof_rule_type *rule_type)
   11013                 :            : {
   11014         [ #  # ]:          0 :         for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
   11015         [ #  # ]:          0 :                 if (item->type == (typeof(item->type))
   11016                 :            :                                   MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL) {
   11017                 :          0 :                         *rule_type = MLX5_TUNNEL_OFFLOAD_MATCH_RULE;
   11018                 :          0 :                         return flow_items_to_tunnel(item);
   11019                 :            :                 }
   11020                 :            :         }
   11021         [ #  # ]:          0 :         for (; action->conf != RTE_FLOW_ACTION_TYPE_END; action++) {
   11022         [ #  # ]:          0 :                 if (action->type == (typeof(action->type))
   11023                 :            :                                     MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET) {
   11024                 :          0 :                         *rule_type = MLX5_TUNNEL_OFFLOAD_SET_RULE;
   11025                 :          0 :                         return flow_actions_to_tunnel(action);
   11026                 :            :                 }
   11027                 :            :         }
   11028                 :            :         return NULL;
   11029                 :            : }
   11030                 :            : 
   11031                 :            : /**
   11032                 :            :  * tunnel offload functionality is defined for DV environment only
   11033                 :            :  */
   11034                 :            : #ifdef HAVE_IBV_FLOW_DV_SUPPORT
   11035                 :            : __extension__
   11036                 :            : union tunnel_offload_mark {
   11037                 :            :         uint32_t val;
   11038                 :            :         struct {
   11039                 :            :                 uint32_t app_reserve:8;
   11040                 :            :                 uint32_t table_id:15;
   11041                 :            :                 uint32_t transfer:1;
   11042                 :            :                 uint32_t _unused_:8;
   11043                 :            :         };
   11044                 :            : };
   11045                 :            : 
   11046                 :            : static bool
   11047                 :            : mlx5_access_tunnel_offload_db
   11048                 :            :         (struct rte_eth_dev *dev,
   11049                 :            :          bool (*match)(struct rte_eth_dev *,
   11050                 :            :                        struct mlx5_flow_tunnel *, const void *),
   11051                 :            :          void (*hit)(struct rte_eth_dev *, struct mlx5_flow_tunnel *, void *),
   11052                 :            :          void (*miss)(struct rte_eth_dev *, void *),
   11053                 :            :          void *ctx, bool lock_op);
   11054                 :            : 
   11055                 :            : static int
   11056                 :          0 : flow_tunnel_add_default_miss(struct rte_eth_dev *dev,
   11057                 :            :                              struct rte_flow *flow,
   11058                 :            :                              const struct rte_flow_attr *attr,
   11059                 :            :                              const struct rte_flow_action *app_actions,
   11060                 :            :                              uint32_t flow_idx,
   11061                 :            :                              const struct mlx5_flow_tunnel *tunnel,
   11062                 :            :                              struct tunnel_default_miss_ctx *ctx,
   11063                 :            :                              struct rte_flow_error *error)
   11064                 :            : {
   11065                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11066                 :            :         struct mlx5_flow *dev_flow;
   11067                 :          0 :         struct rte_flow_attr miss_attr = *attr;
   11068                 :          0 :         const struct rte_flow_item miss_items[2] = {
   11069                 :            :                 {
   11070                 :            :                         .type = RTE_FLOW_ITEM_TYPE_ETH,
   11071                 :            :                         .spec = NULL,
   11072                 :            :                         .last = NULL,
   11073                 :            :                         .mask = NULL
   11074                 :            :                 },
   11075                 :            :                 {
   11076                 :            :                         .type = RTE_FLOW_ITEM_TYPE_END,
   11077                 :            :                         .spec = NULL,
   11078                 :            :                         .last = NULL,
   11079                 :            :                         .mask = NULL
   11080                 :            :                 }
   11081                 :            :         };
   11082                 :            :         union tunnel_offload_mark mark_id;
   11083                 :            :         struct rte_flow_action_mark miss_mark;
   11084                 :          0 :         struct rte_flow_action miss_actions[3] = {
   11085                 :            :                 [0] = { .type = RTE_FLOW_ACTION_TYPE_MARK, .conf = &miss_mark },
   11086                 :            :                 [2] = { .type = RTE_FLOW_ACTION_TYPE_END,  .conf = NULL }
   11087                 :            :         };
   11088                 :            :         const struct rte_flow_action_jump *jump_data;
   11089                 :          0 :         uint32_t i, flow_table = 0; /* prevent compilation warning */
   11090                 :          0 :         struct flow_grp_info grp_info = {
   11091                 :            :                 .external = 1,
   11092                 :          0 :                 .transfer = attr->transfer,
   11093                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
   11094                 :            :                 .std_tbl_fix = 0,
   11095                 :            :         };
   11096                 :            :         int ret;
   11097                 :            : 
   11098         [ #  # ]:          0 :         if (!attr->transfer) {
   11099                 :            :                 uint32_t q_size;
   11100                 :            : 
   11101                 :          0 :                 miss_actions[1].type = RTE_FLOW_ACTION_TYPE_RSS;
   11102                 :          0 :                 q_size = priv->reta_idx_n * sizeof(ctx->queue[0]);
   11103                 :          0 :                 ctx->queue = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO, q_size,
   11104                 :            :                                          0, SOCKET_ID_ANY);
   11105         [ #  # ]:          0 :                 if (!ctx->queue)
   11106                 :          0 :                         return rte_flow_error_set
   11107                 :            :                                 (error, ENOMEM,
   11108                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION_CONF,
   11109                 :            :                                 NULL, "invalid default miss RSS");
   11110                 :          0 :                 ctx->action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
   11111                 :          0 :                 ctx->action_rss.level = 0,
   11112                 :          0 :                 ctx->action_rss.types = priv->rss_conf.rss_hf,
   11113                 :          0 :                 ctx->action_rss.key_len = priv->rss_conf.rss_key_len,
   11114                 :          0 :                 ctx->action_rss.queue_num = priv->reta_idx_n,
   11115                 :          0 :                 ctx->action_rss.key = priv->rss_conf.rss_key,
   11116                 :          0 :                 ctx->action_rss.queue = ctx->queue;
   11117   [ #  #  #  # ]:          0 :                 if (!priv->reta_idx_n || !priv->rxqs_n)
   11118                 :          0 :                         return rte_flow_error_set
   11119                 :            :                                 (error, EINVAL,
   11120                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION_CONF,
   11121                 :            :                                 NULL, "invalid port configuration");
   11122         [ #  # ]:          0 :                 if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG))
   11123                 :          0 :                         ctx->action_rss.types = 0;
   11124         [ #  # ]:          0 :                 for (i = 0; i != priv->reta_idx_n; ++i)
   11125                 :          0 :                         ctx->queue[i] = (*priv->reta_idx)[i];
   11126                 :            :         } else {
   11127                 :          0 :                 miss_actions[1].type = RTE_FLOW_ACTION_TYPE_JUMP;
   11128                 :          0 :                 ctx->miss_jump.group = MLX5_TNL_MISS_FDB_JUMP_GRP;
   11129                 :            :         }
   11130                 :          0 :         miss_actions[1].conf = (typeof(miss_actions[1].conf))ctx->raw;
   11131         [ #  # ]:          0 :         for (; app_actions->type != RTE_FLOW_ACTION_TYPE_JUMP; app_actions++);
   11132                 :          0 :         jump_data = app_actions->conf;
   11133                 :          0 :         miss_attr.priority = MLX5_TNL_MISS_RULE_PRIORITY;
   11134                 :          0 :         miss_attr.group = jump_data->group;
   11135                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, jump_data->group,
   11136                 :            :                                        &flow_table, &grp_info, error);
   11137         [ #  # ]:          0 :         if (ret)
   11138                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   11139                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
   11140                 :            :                                           NULL, "invalid tunnel id");
   11141                 :          0 :         mark_id.app_reserve = 0;
   11142                 :          0 :         mark_id.table_id = tunnel_flow_tbl_to_id(flow_table);
   11143                 :          0 :         mark_id.transfer = !!attr->transfer;
   11144                 :          0 :         mark_id._unused_ = 0;
   11145                 :          0 :         miss_mark.id = mark_id.val;
   11146                 :            :         dev_flow = flow_drv_prepare(dev, flow, &miss_attr,
   11147                 :            :                                     miss_items, miss_actions, flow_idx, error);
   11148         [ #  # ]:          0 :         if (!dev_flow)
   11149                 :          0 :                 return -rte_errno;
   11150                 :          0 :         dev_flow->flow = flow;
   11151                 :          0 :         dev_flow->external = true;
   11152                 :          0 :         dev_flow->tunnel = tunnel;
   11153                 :          0 :         dev_flow->tof_type = MLX5_TUNNEL_OFFLOAD_MISS_RULE;
   11154                 :            :         /* Subflow object was created, we must include one in the list. */
   11155                 :          0 :         SILIST_INSERT(&flow->dev_handles, dev_flow->handle_idx,
   11156                 :            :                       dev_flow->handle, next);
   11157                 :          0 :         DRV_LOG(DEBUG,
   11158                 :            :                 "port %u tunnel type=%d id=%u miss rule priority=%u group=%u",
   11159                 :            :                 dev->data->port_id, tunnel->app_tunnel.type,
   11160                 :            :                 tunnel->tunnel_id, miss_attr.priority, miss_attr.group);
   11161                 :            :         ret = flow_drv_translate(dev, dev_flow, &miss_attr, miss_items,
   11162                 :            :                                   miss_actions, error);
   11163         [ #  # ]:          0 :         if (!ret)
   11164                 :          0 :                 ret = flow_mreg_update_copy_table(dev, flow, miss_actions,
   11165                 :            :                                                   error);
   11166                 :            : 
   11167                 :            :         return ret;
   11168                 :            : }
   11169                 :            : 
   11170                 :            : static const struct mlx5_flow_tbl_data_entry  *
   11171                 :          0 : tunnel_mark_decode(struct rte_eth_dev *dev, uint32_t mark)
   11172                 :            : {
   11173                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11174                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   11175                 :            :         struct mlx5_list_entry *he;
   11176                 :          0 :         union tunnel_offload_mark mbits = { .val = mark };
   11177                 :          0 :         union mlx5_flow_tbl_key table_key = {
   11178                 :            :                 {
   11179                 :          0 :                         .level = tunnel_id_to_flow_tbl(mbits.table_id),
   11180                 :            :                         .id = 0,
   11181                 :            :                         .reserved = 0,
   11182                 :            :                         .dummy = 0,
   11183                 :          0 :                         .is_fdb = !!mbits.transfer,
   11184                 :            :                         .is_egress = 0,
   11185                 :            :                 }
   11186                 :            :         };
   11187                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   11188                 :            :                 .data = &table_key.v64,
   11189                 :            :         };
   11190                 :            : 
   11191                 :          0 :         he = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64, &ctx);
   11192                 :            :         return he ?
   11193         [ #  # ]:          0 :                container_of(he, struct mlx5_flow_tbl_data_entry, entry) : NULL;
   11194                 :            : }
   11195                 :            : 
   11196                 :            : static void
   11197                 :          0 : mlx5_flow_tunnel_grp2tbl_remove_cb(void *tool_ctx,
   11198                 :            :                                    struct mlx5_list_entry *entry)
   11199                 :            : {
   11200                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11201                 :            :         struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash);
   11202                 :            : 
   11203                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TNL_TBL_ID],
   11204                 :            :                         tunnel_flow_tbl_to_id(tte->flow_table));
   11205                 :          0 :         mlx5_free(tte);
   11206                 :          0 : }
   11207                 :            : 
   11208                 :            : static int
   11209                 :          0 : mlx5_flow_tunnel_grp2tbl_match_cb(void *tool_ctx __rte_unused,
   11210                 :            :                                   struct mlx5_list_entry *entry, void *cb_ctx)
   11211                 :            : {
   11212                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11213                 :            :         union tunnel_tbl_key tbl = {
   11214                 :          0 :                 .val = *(uint64_t *)(ctx->data),
   11215                 :            :         };
   11216                 :            :         struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash);
   11217                 :            : 
   11218   [ #  #  #  # ]:          0 :         return tbl.tunnel_id != tte->tunnel_id || tbl.group != tte->group;
   11219                 :            : }
   11220                 :            : 
   11221                 :            : static struct mlx5_list_entry *
   11222                 :          0 : mlx5_flow_tunnel_grp2tbl_create_cb(void *tool_ctx, void *cb_ctx)
   11223                 :            : {
   11224                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11225                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11226                 :            :         struct tunnel_tbl_entry *tte;
   11227                 :            :         union tunnel_tbl_key tbl = {
   11228                 :          0 :                 .val = *(uint64_t *)(ctx->data),
   11229                 :            :         };
   11230                 :            : 
   11231                 :          0 :         tte = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO,
   11232                 :            :                           sizeof(*tte), 0,
   11233                 :            :                           SOCKET_ID_ANY);
   11234         [ #  # ]:          0 :         if (!tte)
   11235                 :          0 :                 goto err;
   11236                 :          0 :         mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_TNL_TBL_ID],
   11237                 :            :                           &tte->flow_table);
   11238         [ #  # ]:          0 :         if (tte->flow_table >= MLX5_MAX_TABLES) {
   11239                 :          0 :                 DRV_LOG(ERR, "Tunnel TBL ID %d exceed max limit.",
   11240                 :            :                         tte->flow_table);
   11241                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TNL_TBL_ID],
   11242                 :            :                                 tte->flow_table);
   11243                 :          0 :                 goto err;
   11244         [ #  # ]:          0 :         } else if (!tte->flow_table) {
   11245                 :          0 :                 goto err;
   11246                 :            :         }
   11247                 :          0 :         tte->flow_table = tunnel_id_to_flow_tbl(tte->flow_table);
   11248                 :          0 :         tte->tunnel_id = tbl.tunnel_id;
   11249                 :          0 :         tte->group = tbl.group;
   11250                 :          0 :         return &tte->hash;
   11251                 :          0 : err:
   11252         [ #  # ]:          0 :         if (tte)
   11253                 :          0 :                 mlx5_free(tte);
   11254                 :            :         return NULL;
   11255                 :            : }
   11256                 :            : 
   11257                 :            : static struct mlx5_list_entry *
   11258                 :          0 : mlx5_flow_tunnel_grp2tbl_clone_cb(void *tool_ctx __rte_unused,
   11259                 :            :                                   struct mlx5_list_entry *oentry,
   11260                 :            :                                   void *cb_ctx __rte_unused)
   11261                 :            : {
   11262                 :          0 :         struct tunnel_tbl_entry *tte = mlx5_malloc(MLX5_MEM_SYS, sizeof(*tte),
   11263                 :            :                                                    0, SOCKET_ID_ANY);
   11264                 :            : 
   11265         [ #  # ]:          0 :         if (!tte)
   11266                 :            :                 return NULL;
   11267                 :            :         memcpy(tte, oentry, sizeof(*tte));
   11268                 :          0 :         return &tte->hash;
   11269                 :            : }
   11270                 :            : 
   11271                 :            : static void
   11272                 :          0 : mlx5_flow_tunnel_grp2tbl_clone_free_cb(void *tool_ctx __rte_unused,
   11273                 :            :                                        struct mlx5_list_entry *entry)
   11274                 :            : {
   11275                 :            :         struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash);
   11276                 :            : 
   11277                 :          0 :         mlx5_free(tte);
   11278                 :          0 : }
   11279                 :            : 
   11280                 :            : static uint32_t
   11281                 :          0 : tunnel_flow_group_to_flow_table(struct rte_eth_dev *dev,
   11282                 :            :                                 const struct mlx5_flow_tunnel *tunnel,
   11283                 :            :                                 uint32_t group, uint32_t *table,
   11284                 :            :                                 struct rte_flow_error *error)
   11285                 :            : {
   11286                 :            :         struct mlx5_list_entry *he;
   11287                 :            :         struct tunnel_tbl_entry *tte;
   11288         [ #  # ]:          0 :         union tunnel_tbl_key key = {
   11289         [ #  # ]:          0 :                 .tunnel_id = tunnel ? tunnel->tunnel_id : 0,
   11290                 :            :                 .group = group
   11291                 :            :         };
   11292                 :            :         struct mlx5_flow_tunnel_hub *thub = mlx5_tunnel_hub(dev);
   11293                 :            :         struct mlx5_hlist *group_hash;
   11294                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   11295                 :            :                 .data = &key.val,
   11296                 :            :         };
   11297                 :            : 
   11298         [ #  # ]:          0 :         group_hash = tunnel ? tunnel->groups : thub->groups;
   11299                 :          0 :         he = mlx5_hlist_register(group_hash, key.val, &ctx);
   11300         [ #  # ]:          0 :         if (!he)
   11301                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   11302                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
   11303                 :            :                                           NULL,
   11304                 :            :                                           "tunnel group index not supported");
   11305                 :            :         tte = container_of(he, typeof(*tte), hash);
   11306                 :          0 :         *table = tte->flow_table;
   11307                 :          0 :         DRV_LOG(DEBUG, "port %u tunnel %u group=%#x table=%#x",
   11308                 :            :                 dev->data->port_id, key.tunnel_id, group, *table);
   11309                 :          0 :         return 0;
   11310                 :            : }
   11311                 :            : 
   11312                 :            : static void
   11313                 :          0 : mlx5_flow_tunnel_free(struct rte_eth_dev *dev,
   11314                 :            :                       struct mlx5_flow_tunnel *tunnel)
   11315                 :            : {
   11316                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11317                 :            :         struct mlx5_indexed_pool *ipool;
   11318                 :            : 
   11319                 :          0 :         DRV_LOG(DEBUG, "port %u release pmd tunnel id=0x%x",
   11320                 :            :                 dev->data->port_id, tunnel->tunnel_id);
   11321         [ #  # ]:          0 :         LIST_REMOVE(tunnel, chain);
   11322                 :          0 :         mlx5_hlist_destroy(tunnel->groups);
   11323                 :          0 :         ipool = priv->sh->ipool[MLX5_IPOOL_TUNNEL_ID];
   11324                 :          0 :         mlx5_ipool_free(ipool, tunnel->tunnel_id);
   11325                 :          0 : }
   11326                 :            : 
   11327                 :            : static bool
   11328                 :          0 : mlx5_access_tunnel_offload_db
   11329                 :            :         (struct rte_eth_dev *dev,
   11330                 :            :          bool (*match)(struct rte_eth_dev *,
   11331                 :            :                        struct mlx5_flow_tunnel *, const void *),
   11332                 :            :          void (*hit)(struct rte_eth_dev *, struct mlx5_flow_tunnel *, void *),
   11333                 :            :          void (*miss)(struct rte_eth_dev *, void *),
   11334                 :            :          void *ctx, bool lock_op)
   11335                 :            : {
   11336                 :            :         bool verdict = false;
   11337                 :            :         struct mlx5_flow_tunnel_hub *thub = mlx5_tunnel_hub(dev);
   11338                 :            :         struct mlx5_flow_tunnel *tunnel;
   11339                 :            : 
   11340                 :          0 :         rte_spinlock_lock(&thub->sl);
   11341         [ #  # ]:          0 :         LIST_FOREACH(tunnel, &thub->tunnels, chain) {
   11342                 :          0 :                 verdict = match(dev, tunnel, (const void *)ctx);
   11343         [ #  # ]:          0 :                 if (verdict)
   11344                 :            :                         break;
   11345                 :            :         }
   11346         [ #  # ]:          0 :         if (!lock_op)
   11347                 :            :                 rte_spinlock_unlock(&thub->sl);
   11348         [ #  # ]:          0 :         if (verdict && hit)
   11349                 :          0 :                 hit(dev, tunnel, ctx);
   11350         [ #  # ]:          0 :         if (!verdict && miss)
   11351                 :          0 :                 miss(dev, ctx);
   11352         [ #  # ]:          0 :         if (lock_op)
   11353                 :            :                 rte_spinlock_unlock(&thub->sl);
   11354                 :            : 
   11355                 :          0 :         return verdict;
   11356                 :            : }
   11357                 :            : 
   11358                 :            : struct tunnel_db_find_tunnel_id_ctx {
   11359                 :            :         uint32_t tunnel_id;
   11360                 :            :         struct mlx5_flow_tunnel *tunnel;
   11361                 :            : };
   11362                 :            : 
   11363                 :            : static bool
   11364                 :          0 : find_tunnel_id_match(struct rte_eth_dev *dev,
   11365                 :            :                      struct mlx5_flow_tunnel *tunnel, const void *x)
   11366                 :            : {
   11367                 :            :         const struct tunnel_db_find_tunnel_id_ctx *ctx = x;
   11368                 :            : 
   11369                 :            :         RTE_SET_USED(dev);
   11370                 :          0 :         return tunnel->tunnel_id == ctx->tunnel_id;
   11371                 :            : }
   11372                 :            : 
   11373                 :            : static void
   11374                 :          0 : find_tunnel_id_hit(struct rte_eth_dev *dev,
   11375                 :            :                    struct mlx5_flow_tunnel *tunnel, void *x)
   11376                 :            : {
   11377                 :            :         struct tunnel_db_find_tunnel_id_ctx *ctx = x;
   11378                 :            :         RTE_SET_USED(dev);
   11379                 :          0 :         ctx->tunnel = tunnel;
   11380                 :          0 : }
   11381                 :            : 
   11382                 :            : static struct mlx5_flow_tunnel *
   11383                 :            : mlx5_find_tunnel_id(struct rte_eth_dev *dev, uint32_t id)
   11384                 :            : {
   11385                 :          0 :         struct tunnel_db_find_tunnel_id_ctx ctx = {
   11386                 :            :                 .tunnel_id = id,
   11387                 :            :         };
   11388                 :            : 
   11389                 :          0 :         mlx5_access_tunnel_offload_db(dev, find_tunnel_id_match,
   11390                 :            :                                       find_tunnel_id_hit, NULL, &ctx, true);
   11391                 :            : 
   11392         [ #  # ]:          0 :         return ctx.tunnel;
   11393                 :            : }
   11394                 :            : 
   11395                 :            : static struct mlx5_flow_tunnel *
   11396                 :          0 : mlx5_flow_tunnel_allocate(struct rte_eth_dev *dev,
   11397                 :            :                           const struct rte_flow_tunnel *app_tunnel)
   11398                 :            : {
   11399                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11400                 :            :         struct mlx5_indexed_pool *ipool;
   11401                 :            :         struct mlx5_flow_tunnel *tunnel;
   11402                 :            :         uint32_t id;
   11403                 :            : 
   11404                 :          0 :         ipool = priv->sh->ipool[MLX5_IPOOL_TUNNEL_ID];
   11405                 :          0 :         tunnel = mlx5_ipool_zmalloc(ipool, &id);
   11406         [ #  # ]:          0 :         if (!tunnel)
   11407                 :            :                 return NULL;
   11408         [ #  # ]:          0 :         if (id >= MLX5_MAX_TUNNELS) {
   11409                 :          0 :                 mlx5_ipool_free(ipool, id);
   11410                 :          0 :                 DRV_LOG(ERR, "Tunnel ID %d exceed max limit.", id);
   11411                 :          0 :                 return NULL;
   11412                 :            :         }
   11413                 :          0 :         tunnel->groups = mlx5_hlist_create("tunnel groups", 64, false, true,
   11414                 :          0 :                                            priv->sh,
   11415                 :            :                                            mlx5_flow_tunnel_grp2tbl_create_cb,
   11416                 :            :                                            mlx5_flow_tunnel_grp2tbl_match_cb,
   11417                 :            :                                            mlx5_flow_tunnel_grp2tbl_remove_cb,
   11418                 :            :                                            mlx5_flow_tunnel_grp2tbl_clone_cb,
   11419                 :            :                                         mlx5_flow_tunnel_grp2tbl_clone_free_cb);
   11420         [ #  # ]:          0 :         if (!tunnel->groups) {
   11421                 :          0 :                 mlx5_ipool_free(ipool, id);
   11422                 :          0 :                 return NULL;
   11423                 :            :         }
   11424                 :            :         /* initiate new PMD tunnel */
   11425                 :          0 :         memcpy(&tunnel->app_tunnel, app_tunnel, sizeof(*app_tunnel));
   11426                 :          0 :         tunnel->tunnel_id = id;
   11427                 :          0 :         tunnel->action.type = (typeof(tunnel->action.type))
   11428                 :            :                               MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET;
   11429                 :          0 :         tunnel->action.conf = tunnel;
   11430                 :          0 :         tunnel->item.type = (typeof(tunnel->item.type))
   11431                 :            :                             MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL;
   11432                 :          0 :         tunnel->item.spec = tunnel;
   11433                 :          0 :         tunnel->item.last = NULL;
   11434                 :          0 :         tunnel->item.mask = NULL;
   11435                 :            : 
   11436                 :          0 :         DRV_LOG(DEBUG, "port %u new pmd tunnel id=0x%x",
   11437                 :            :                 dev->data->port_id, tunnel->tunnel_id);
   11438                 :            : 
   11439                 :          0 :         return tunnel;
   11440                 :            : }
   11441                 :            : 
   11442                 :            : struct tunnel_db_get_tunnel_ctx {
   11443                 :            :         const struct rte_flow_tunnel *app_tunnel;
   11444                 :            :         struct mlx5_flow_tunnel *tunnel;
   11445                 :            : };
   11446                 :            : 
   11447                 :          0 : static bool get_tunnel_match(struct rte_eth_dev *dev,
   11448                 :            :                              struct mlx5_flow_tunnel *tunnel, const void *x)
   11449                 :            : {
   11450                 :            :         const struct tunnel_db_get_tunnel_ctx *ctx = x;
   11451                 :            : 
   11452                 :            :         RTE_SET_USED(dev);
   11453                 :          0 :         return !memcmp(ctx->app_tunnel, &tunnel->app_tunnel,
   11454                 :            :                        sizeof(*ctx->app_tunnel));
   11455                 :            : }
   11456                 :            : 
   11457                 :          0 : static void get_tunnel_hit(struct rte_eth_dev *dev,
   11458                 :            :                            struct mlx5_flow_tunnel *tunnel, void *x)
   11459                 :            : {
   11460                 :            :         /* called under tunnel spinlock protection */
   11461                 :            :         struct tunnel_db_get_tunnel_ctx *ctx = x;
   11462                 :            : 
   11463                 :            :         RTE_SET_USED(dev);
   11464                 :          0 :         tunnel->refctn++;
   11465                 :          0 :         ctx->tunnel = tunnel;
   11466                 :          0 : }
   11467                 :            : 
   11468                 :          0 : static void get_tunnel_miss(struct rte_eth_dev *dev, void *x)
   11469                 :            : {
   11470                 :            :         /* called under tunnel spinlock protection */
   11471                 :            :         struct mlx5_flow_tunnel_hub *thub = mlx5_tunnel_hub(dev);
   11472                 :            :         struct tunnel_db_get_tunnel_ctx *ctx = x;
   11473                 :            : 
   11474                 :          0 :         rte_spinlock_unlock(&thub->sl);
   11475                 :          0 :         ctx->tunnel = mlx5_flow_tunnel_allocate(dev, ctx->app_tunnel);
   11476                 :            :         rte_spinlock_lock(&thub->sl);
   11477         [ #  # ]:          0 :         if (ctx->tunnel) {
   11478                 :          0 :                 ctx->tunnel->refctn = 1;
   11479         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&thub->tunnels, ctx->tunnel, chain);
   11480                 :            :         }
   11481                 :          0 : }
   11482                 :            : 
   11483                 :            : 
   11484                 :            : static int
   11485                 :          0 : mlx5_get_flow_tunnel(struct rte_eth_dev *dev,
   11486                 :            :                      const struct rte_flow_tunnel *app_tunnel,
   11487                 :            :                      struct mlx5_flow_tunnel **tunnel)
   11488                 :            : {
   11489                 :          0 :         struct tunnel_db_get_tunnel_ctx ctx = {
   11490                 :            :                 .app_tunnel = app_tunnel,
   11491                 :            :         };
   11492                 :            : 
   11493                 :          0 :         mlx5_access_tunnel_offload_db(dev, get_tunnel_match, get_tunnel_hit,
   11494                 :            :                                       get_tunnel_miss, &ctx, true);
   11495                 :          0 :         *tunnel = ctx.tunnel;
   11496         [ #  # ]:          0 :         return ctx.tunnel ? 0 : -ENOMEM;
   11497                 :            : }
   11498                 :            : 
   11499                 :          0 : void mlx5_release_tunnel_hub(struct mlx5_dev_ctx_shared *sh, uint16_t port_id)
   11500                 :            : {
   11501                 :          0 :         struct mlx5_flow_tunnel_hub *thub = sh->tunnel_hub;
   11502                 :            : 
   11503         [ #  # ]:          0 :         if (!thub)
   11504                 :            :                 return;
   11505         [ #  # ]:          0 :         if (!LIST_EMPTY(&thub->tunnels))
   11506                 :          0 :                 DRV_LOG(WARNING, "port %u tunnels present", port_id);
   11507                 :          0 :         mlx5_hlist_destroy(thub->groups);
   11508                 :          0 :         mlx5_free(thub);
   11509                 :            : }
   11510                 :            : 
   11511                 :          0 : int mlx5_alloc_tunnel_hub(struct mlx5_dev_ctx_shared *sh)
   11512                 :            : {
   11513                 :            :         int err;
   11514                 :            :         struct mlx5_flow_tunnel_hub *thub;
   11515                 :            : 
   11516                 :          0 :         thub = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO, sizeof(*thub),
   11517                 :            :                            0, SOCKET_ID_ANY);
   11518         [ #  # ]:          0 :         if (!thub)
   11519                 :            :                 return -ENOMEM;
   11520                 :          0 :         LIST_INIT(&thub->tunnels);
   11521                 :            :         rte_spinlock_init(&thub->sl);
   11522                 :          0 :         thub->groups = mlx5_hlist_create("flow groups", 64,
   11523                 :            :                                          false, true, sh,
   11524                 :            :                                          mlx5_flow_tunnel_grp2tbl_create_cb,
   11525                 :            :                                          mlx5_flow_tunnel_grp2tbl_match_cb,
   11526                 :            :                                          mlx5_flow_tunnel_grp2tbl_remove_cb,
   11527                 :            :                                          mlx5_flow_tunnel_grp2tbl_clone_cb,
   11528                 :            :                                         mlx5_flow_tunnel_grp2tbl_clone_free_cb);
   11529         [ #  # ]:          0 :         if (!thub->groups) {
   11530                 :          0 :                 err = -rte_errno;
   11531                 :          0 :                 goto err;
   11532                 :            :         }
   11533                 :          0 :         sh->tunnel_hub = thub;
   11534                 :            : 
   11535                 :          0 :         return 0;
   11536                 :            : 
   11537                 :            : err:
   11538                 :            :         if (thub->groups)
   11539                 :            :                 mlx5_hlist_destroy(thub->groups);
   11540                 :            :         if (thub)
   11541                 :          0 :                 mlx5_free(thub);
   11542                 :          0 :         return err;
   11543                 :            : }
   11544                 :            : 
   11545                 :            : static inline int
   11546                 :          0 : mlx5_flow_tunnel_validate(struct rte_eth_dev *dev,
   11547                 :            :                           struct rte_flow_tunnel *tunnel,
   11548                 :            :                           struct rte_flow_error *error)
   11549                 :            : {
   11550                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11551                 :            : 
   11552         [ #  # ]:          0 :         if (!priv->sh->config.dv_flow_en)
   11553                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   11554                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
   11555                 :            :                                           "flow DV interface is off");
   11556         [ #  # ]:          0 :         if (!is_tunnel_offload_active(dev))
   11557                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   11558                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
   11559                 :            :                                           "tunnel offload was not activated, consider setting dv_xmeta_en=3");
   11560         [ #  # ]:          0 :         if (!tunnel)
   11561                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   11562                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
   11563                 :            :                                           "no application tunnel");
   11564         [ #  # ]:          0 :         switch (tunnel->type) {
   11565                 :          0 :         default:
   11566                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   11567                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
   11568                 :            :                                           "unsupported tunnel type");
   11569                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN:
   11570                 :            :         case RTE_FLOW_ITEM_TYPE_GRE:
   11571                 :            :         case RTE_FLOW_ITEM_TYPE_NVGRE:
   11572                 :            :         case RTE_FLOW_ITEM_TYPE_GENEVE:
   11573                 :            :                 break;
   11574                 :            :         }
   11575                 :            :         return 0;
   11576                 :            : }
   11577                 :            : 
   11578                 :            : static int
   11579                 :          0 : mlx5_flow_tunnel_decap_set(struct rte_eth_dev *dev,
   11580                 :            :                     struct rte_flow_tunnel *app_tunnel,
   11581                 :            :                     struct rte_flow_action **actions,
   11582                 :            :                     uint32_t *num_of_actions,
   11583                 :            :                     struct rte_flow_error *error)
   11584                 :            : {
   11585                 :            :         struct mlx5_flow_tunnel *tunnel;
   11586                 :          0 :         int ret = mlx5_flow_tunnel_validate(dev, app_tunnel, error);
   11587                 :            : 
   11588         [ #  # ]:          0 :         if (ret)
   11589                 :            :                 return ret;
   11590                 :          0 :         ret = mlx5_get_flow_tunnel(dev, app_tunnel, &tunnel);
   11591         [ #  # ]:          0 :         if (ret < 0) {
   11592                 :          0 :                 return rte_flow_error_set(error, ret,
   11593                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
   11594                 :            :                                           "failed to initialize pmd tunnel");
   11595                 :            :         }
   11596                 :          0 :         *actions = &tunnel->action;
   11597                 :          0 :         *num_of_actions = 1;
   11598                 :          0 :         return 0;
   11599                 :            : }
   11600                 :            : 
   11601                 :            : static int
   11602                 :          0 : mlx5_flow_tunnel_match(struct rte_eth_dev *dev,
   11603                 :            :                        struct rte_flow_tunnel *app_tunnel,
   11604                 :            :                        struct rte_flow_item **items,
   11605                 :            :                        uint32_t *num_of_items,
   11606                 :            :                        struct rte_flow_error *error)
   11607                 :            : {
   11608                 :            :         struct mlx5_flow_tunnel *tunnel;
   11609                 :          0 :         int ret = mlx5_flow_tunnel_validate(dev, app_tunnel, error);
   11610                 :            : 
   11611         [ #  # ]:          0 :         if (ret)
   11612                 :            :                 return ret;
   11613                 :          0 :         ret = mlx5_get_flow_tunnel(dev, app_tunnel, &tunnel);
   11614         [ #  # ]:          0 :         if (ret < 0) {
   11615                 :          0 :                 return rte_flow_error_set(error, ret,
   11616                 :            :                                           RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
   11617                 :            :                                           "failed to initialize pmd tunnel");
   11618                 :            :         }
   11619                 :          0 :         *items = &tunnel->item;
   11620                 :          0 :         *num_of_items = 1;
   11621                 :          0 :         return 0;
   11622                 :            : }
   11623                 :            : 
   11624                 :            : struct tunnel_db_element_release_ctx {
   11625                 :            :         struct rte_flow_item *items;
   11626                 :            :         struct rte_flow_action *actions;
   11627                 :            :         uint32_t num_elements;
   11628                 :            :         struct rte_flow_error *error;
   11629                 :            :         int ret;
   11630                 :            : };
   11631                 :            : 
   11632                 :            : static bool
   11633                 :          0 : tunnel_element_release_match(struct rte_eth_dev *dev,
   11634                 :            :                              struct mlx5_flow_tunnel *tunnel, const void *x)
   11635                 :            : {
   11636                 :            :         const struct tunnel_db_element_release_ctx *ctx = x;
   11637                 :            : 
   11638                 :            :         RTE_SET_USED(dev);
   11639         [ #  # ]:          0 :         if (ctx->num_elements != 1)
   11640                 :            :                 return false;
   11641         [ #  # ]:          0 :         else if (ctx->items)
   11642                 :          0 :                 return ctx->items == &tunnel->item;
   11643         [ #  # ]:          0 :         else if (ctx->actions)
   11644                 :          0 :                 return ctx->actions == &tunnel->action;
   11645                 :            : 
   11646                 :            :         return false;
   11647                 :            : }
   11648                 :            : 
   11649                 :            : static void
   11650                 :          0 : tunnel_element_release_hit(struct rte_eth_dev *dev,
   11651                 :            :                            struct mlx5_flow_tunnel *tunnel, void *x)
   11652                 :            : {
   11653                 :            :         struct tunnel_db_element_release_ctx *ctx = x;
   11654                 :          0 :         ctx->ret = 0;
   11655         [ #  # ]:          0 :         if (!(rte_atomic_fetch_sub_explicit(&tunnel->refctn, 1, rte_memory_order_relaxed) - 1))
   11656                 :          0 :                 mlx5_flow_tunnel_free(dev, tunnel);
   11657                 :          0 : }
   11658                 :            : 
   11659                 :            : static void
   11660                 :          0 : tunnel_element_release_miss(struct rte_eth_dev *dev, void *x)
   11661                 :            : {
   11662                 :            :         struct tunnel_db_element_release_ctx *ctx = x;
   11663                 :            :         RTE_SET_USED(dev);
   11664                 :          0 :         ctx->ret = rte_flow_error_set(ctx->error, EINVAL,
   11665                 :            :                                       RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
   11666                 :            :                                       "invalid argument");
   11667                 :          0 : }
   11668                 :            : 
   11669                 :            : static int
   11670                 :          0 : mlx5_flow_tunnel_item_release(struct rte_eth_dev *dev,
   11671                 :            :                        struct rte_flow_item *pmd_items,
   11672                 :            :                        uint32_t num_items, struct rte_flow_error *err)
   11673                 :            : {
   11674                 :          0 :         struct tunnel_db_element_release_ctx ctx = {
   11675                 :            :                 .items = pmd_items,
   11676                 :            :                 .actions = NULL,
   11677                 :            :                 .num_elements = num_items,
   11678                 :            :                 .error = err,
   11679                 :            :         };
   11680                 :            : 
   11681                 :          0 :         mlx5_access_tunnel_offload_db(dev, tunnel_element_release_match,
   11682                 :            :                                       tunnel_element_release_hit,
   11683                 :            :                                       tunnel_element_release_miss, &ctx, false);
   11684                 :            : 
   11685                 :          0 :         return ctx.ret;
   11686                 :            : }
   11687                 :            : 
   11688                 :            : static int
   11689                 :          0 : mlx5_flow_tunnel_action_release(struct rte_eth_dev *dev,
   11690                 :            :                          struct rte_flow_action *pmd_actions,
   11691                 :            :                          uint32_t num_actions, struct rte_flow_error *err)
   11692                 :            : {
   11693                 :          0 :         struct tunnel_db_element_release_ctx ctx = {
   11694                 :            :                 .items = NULL,
   11695                 :            :                 .actions = pmd_actions,
   11696                 :            :                 .num_elements = num_actions,
   11697                 :            :                 .error = err,
   11698                 :            :         };
   11699                 :            : 
   11700                 :          0 :         mlx5_access_tunnel_offload_db(dev, tunnel_element_release_match,
   11701                 :            :                                       tunnel_element_release_hit,
   11702                 :            :                                       tunnel_element_release_miss, &ctx, false);
   11703                 :            : 
   11704                 :          0 :         return ctx.ret;
   11705                 :            : }
   11706                 :            : 
   11707                 :            : static int
   11708                 :          0 : mlx5_flow_tunnel_get_restore_info(struct rte_eth_dev *dev,
   11709                 :            :                                   struct rte_mbuf *m,
   11710                 :            :                                   struct rte_flow_restore_info *info,
   11711                 :            :                                   struct rte_flow_error *err)
   11712                 :            : {
   11713                 :          0 :         uint64_t ol_flags = m->ol_flags;
   11714                 :            :         const struct mlx5_flow_tbl_data_entry *tble;
   11715                 :            :         const uint64_t mask = RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
   11716                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11717                 :            : 
   11718         [ #  # ]:          0 :         if (priv->tunnel_enabled == 0)
   11719                 :          0 :                 goto err;
   11720         [ #  # ]:          0 :         if ((ol_flags & mask) != mask)
   11721                 :          0 :                 goto err;
   11722                 :          0 :         tble = tunnel_mark_decode(dev, m->hash.fdir.hi);
   11723         [ #  # ]:          0 :         if (!tble) {
   11724                 :          0 :                 DRV_LOG(DEBUG, "port %u invalid miss tunnel mark %#x",
   11725                 :            :                         dev->data->port_id, m->hash.fdir.hi);
   11726                 :          0 :                 goto err;
   11727                 :            :         }
   11728                 :            :         MLX5_ASSERT(tble->tunnel);
   11729                 :          0 :         memcpy(&info->tunnel, &tble->tunnel->app_tunnel, sizeof(info->tunnel));
   11730                 :          0 :         info->group_id = tble->group_id;
   11731                 :          0 :         info->flags = RTE_FLOW_RESTORE_INFO_TUNNEL |
   11732                 :            :                       RTE_FLOW_RESTORE_INFO_GROUP_ID |
   11733                 :            :                       RTE_FLOW_RESTORE_INFO_ENCAPSULATED;
   11734                 :            : 
   11735                 :          0 :         return 0;
   11736                 :            : 
   11737                 :          0 : err:
   11738                 :          0 :         return rte_flow_error_set(err, EINVAL,
   11739                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11740                 :            :                                   "failed to get restore info");
   11741                 :            : }
   11742                 :            : 
   11743                 :            : #else /* HAVE_IBV_FLOW_DV_SUPPORT */
   11744                 :            : static int
   11745                 :            : mlx5_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
   11746                 :            :                            __rte_unused struct rte_flow_tunnel *app_tunnel,
   11747                 :            :                            __rte_unused struct rte_flow_action **actions,
   11748                 :            :                            __rte_unused uint32_t *num_of_actions,
   11749                 :            :                            __rte_unused struct rte_flow_error *error)
   11750                 :            : {
   11751                 :            :         return -ENOTSUP;
   11752                 :            : }
   11753                 :            : 
   11754                 :            : static int
   11755                 :            : mlx5_flow_tunnel_match(__rte_unused struct rte_eth_dev *dev,
   11756                 :            :                        __rte_unused struct rte_flow_tunnel *app_tunnel,
   11757                 :            :                        __rte_unused struct rte_flow_item **items,
   11758                 :            :                        __rte_unused uint32_t *num_of_items,
   11759                 :            :                        __rte_unused struct rte_flow_error *error)
   11760                 :            : {
   11761                 :            :         return -ENOTSUP;
   11762                 :            : }
   11763                 :            : 
   11764                 :            : static int
   11765                 :            : mlx5_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev,
   11766                 :            :                               __rte_unused struct rte_flow_item *pmd_items,
   11767                 :            :                               __rte_unused uint32_t num_items,
   11768                 :            :                               __rte_unused struct rte_flow_error *err)
   11769                 :            : {
   11770                 :            :         return -ENOTSUP;
   11771                 :            : }
   11772                 :            : 
   11773                 :            : static int
   11774                 :            : mlx5_flow_tunnel_action_release(__rte_unused struct rte_eth_dev *dev,
   11775                 :            :                                 __rte_unused struct rte_flow_action *pmd_action,
   11776                 :            :                                 __rte_unused uint32_t num_actions,
   11777                 :            :                                 __rte_unused struct rte_flow_error *err)
   11778                 :            : {
   11779                 :            :         return -ENOTSUP;
   11780                 :            : }
   11781                 :            : 
   11782                 :            : static int
   11783                 :            : mlx5_flow_tunnel_get_restore_info(__rte_unused struct rte_eth_dev *dev,
   11784                 :            :                                   __rte_unused struct rte_mbuf *m,
   11785                 :            :                                   __rte_unused struct rte_flow_restore_info *i,
   11786                 :            :                                   __rte_unused struct rte_flow_error *err)
   11787                 :            : {
   11788                 :            :         return -ENOTSUP;
   11789                 :            : }
   11790                 :            : 
   11791                 :            : static int
   11792                 :            : flow_tunnel_add_default_miss(__rte_unused struct rte_eth_dev *dev,
   11793                 :            :                              __rte_unused struct rte_flow *flow,
   11794                 :            :                              __rte_unused const struct rte_flow_attr *attr,
   11795                 :            :                              __rte_unused const struct rte_flow_action *actions,
   11796                 :            :                              __rte_unused uint32_t flow_idx,
   11797                 :            :                              __rte_unused const struct mlx5_flow_tunnel *tunnel,
   11798                 :            :                              __rte_unused struct tunnel_default_miss_ctx *ctx,
   11799                 :            :                              __rte_unused struct rte_flow_error *error)
   11800                 :            : {
   11801                 :            :         return -ENOTSUP;
   11802                 :            : }
   11803                 :            : 
   11804                 :            : static struct mlx5_flow_tunnel *
   11805                 :            : mlx5_find_tunnel_id(__rte_unused struct rte_eth_dev *dev,
   11806                 :            :                     __rte_unused uint32_t id)
   11807                 :            : {
   11808                 :            :         return NULL;
   11809                 :            : }
   11810                 :            : 
   11811                 :            : static void
   11812                 :            : mlx5_flow_tunnel_free(__rte_unused struct rte_eth_dev *dev,
   11813                 :            :                       __rte_unused struct mlx5_flow_tunnel *tunnel)
   11814                 :            : {
   11815                 :            : }
   11816                 :            : 
   11817                 :            : static uint32_t
   11818                 :            : tunnel_flow_group_to_flow_table(__rte_unused struct rte_eth_dev *dev,
   11819                 :            :                                 __rte_unused const struct mlx5_flow_tunnel *t,
   11820                 :            :                                 __rte_unused uint32_t group,
   11821                 :            :                                 __rte_unused uint32_t *table,
   11822                 :            :                                 struct rte_flow_error *error)
   11823                 :            : {
   11824                 :            :         return rte_flow_error_set(error, ENOTSUP,
   11825                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11826                 :            :                                   "tunnel offload requires DV support");
   11827                 :            : }
   11828                 :            : 
   11829                 :            : void
   11830                 :            : mlx5_release_tunnel_hub(__rte_unused struct mlx5_dev_ctx_shared *sh,
   11831                 :            :                         __rte_unused  uint16_t port_id)
   11832                 :            : {
   11833                 :            : }
   11834                 :            : #endif /* HAVE_IBV_FLOW_DV_SUPPORT */
   11835                 :            : 
   11836                 :            : /* Flex flow item API */
   11837                 :            : static struct rte_flow_item_flex_handle *
   11838                 :          0 : mlx5_flow_flex_item_create(struct rte_eth_dev *dev,
   11839                 :            :                            const struct rte_flow_item_flex_conf *conf,
   11840                 :            :                            struct rte_flow_error *error)
   11841                 :            : {
   11842                 :            :         static const char err_msg[] = "flex item creation unsupported";
   11843         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11844                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   11845                 :          0 :         const struct mlx5_flow_driver_ops *fops =
   11846                 :            :                         flow_get_drv_ops(flow_get_drv_type(dev, &attr));
   11847                 :            : 
   11848         [ #  # ]:          0 :         if (!priv->pci_dev) {
   11849                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   11850                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11851                 :            :                                    "create flex item on PF only");
   11852                 :          0 :                 return NULL;
   11853                 :            :         }
   11854         [ #  # ]:          0 :         switch (priv->pci_dev->id.device_id) {
   11855                 :            :         case PCI_DEVICE_ID_MELLANOX_BLUEFIELD2:
   11856                 :            :         case PCI_DEVICE_ID_MELLANOX_BLUEFIELD3:
   11857                 :            :                 break;
   11858                 :          0 :         default:
   11859                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   11860                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11861                 :            :                                    "flex item available on BlueField ports only");
   11862                 :          0 :                 return NULL;
   11863                 :            :         }
   11864         [ #  # ]:          0 :         if (!fops->item_create) {
   11865                 :          0 :                 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg);
   11866                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   11867                 :            :                                    NULL, err_msg);
   11868                 :          0 :                 return NULL;
   11869                 :            :         }
   11870                 :          0 :         return fops->item_create(dev, conf, error);
   11871                 :            : }
   11872                 :            : 
   11873                 :            : static int
   11874         [ #  # ]:          0 : mlx5_flow_flex_item_release(struct rte_eth_dev *dev,
   11875                 :            :                             const struct rte_flow_item_flex_handle *handle,
   11876                 :            :                             struct rte_flow_error *error)
   11877                 :            : {
   11878                 :            :         static const char err_msg[] = "flex item release unsupported";
   11879                 :            :         struct rte_flow_attr attr = { .transfer = 0 };
   11880                 :          0 :         const struct mlx5_flow_driver_ops *fops =
   11881                 :            :                         flow_get_drv_ops(flow_get_drv_type(dev, &attr));
   11882                 :            : 
   11883         [ #  # ]:          0 :         if (!fops->item_release) {
   11884                 :          0 :                 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg);
   11885                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   11886                 :            :                                    NULL, err_msg);
   11887                 :          0 :                 return -rte_errno;
   11888                 :            :         }
   11889                 :          0 :         return fops->item_release(dev, handle, error);
   11890                 :            : }
   11891                 :            : 
   11892                 :            : static void
   11893                 :          0 : mlx5_dbg__print_pattern(const struct rte_flow_item *item)
   11894                 :            : {
   11895                 :            :         int ret;
   11896                 :            :         struct rte_flow_error error;
   11897                 :            : 
   11898         [ #  # ]:          0 :         for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
   11899                 :            :                 char *item_name;
   11900                 :          0 :                 ret = rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_NAME_PTR, &item_name,
   11901                 :            :                                     sizeof(item_name),
   11902                 :          0 :                                     (void *)(uintptr_t)item->type, &error);
   11903         [ #  # ]:          0 :                 if (ret > 0)
   11904                 :          0 :                         printf("%s ", item_name);
   11905                 :            :                 else
   11906                 :          0 :                         printf("%d\n", (int)item->type);
   11907                 :            :         }
   11908                 :            :         printf("END\n");
   11909                 :          0 : }
   11910                 :            : 
   11911                 :            : static int
   11912                 :            : mlx5_flow_is_std_vxlan_port(const struct rte_flow_item *udp_item)
   11913                 :            : {
   11914                 :          0 :         const struct rte_flow_item_udp *spec = udp_item->spec;
   11915                 :          0 :         const struct rte_flow_item_udp *mask = udp_item->mask;
   11916                 :            :         uint16_t udp_dport = 0;
   11917                 :            : 
   11918                 :          0 :         if (spec != NULL) {
   11919         [ #  # ]:          0 :                 if (!mask)
   11920                 :            :                         mask = &rte_flow_item_udp_mask;
   11921         [ #  # ]:          0 :                 udp_dport = rte_be_to_cpu_16(spec->hdr.dst_port &
   11922                 :            :                                 mask->hdr.dst_port);
   11923                 :            :         }
   11924                 :          0 :         return (!udp_dport || udp_dport == MLX5_UDP_PORT_VXLAN);
   11925                 :            : }
   11926                 :            : 
   11927                 :            : static const struct mlx5_flow_expand_node *
   11928                 :          0 : mlx5_flow_expand_rss_adjust_node(const struct rte_flow_item *pattern,
   11929                 :            :                 unsigned int item_idx,
   11930                 :            :                 const struct mlx5_flow_expand_node graph[],
   11931                 :            :                 const struct mlx5_flow_expand_node *node)
   11932                 :            : {
   11933                 :          0 :         const struct rte_flow_item *item = pattern + item_idx, *prev_item;
   11934                 :            : 
   11935   [ #  #  #  # ]:          0 :         if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN &&
   11936                 :          0 :                         node != NULL &&
   11937         [ #  # ]:          0 :                         node->type == RTE_FLOW_ITEM_TYPE_VXLAN) {
   11938                 :            :                 /*
   11939                 :            :                  * The expansion node is VXLAN and it is also the last
   11940                 :            :                  * expandable item in the pattern, so need to continue
   11941                 :            :                  * expansion of the inner tunnel.
   11942                 :            :                  */
   11943                 :            :                 MLX5_ASSERT(item_idx > 0);
   11944         [ #  # ]:          0 :                 prev_item = pattern + item_idx - 1;
   11945                 :            :                 MLX5_ASSERT(prev_item->type == RTE_FLOW_ITEM_TYPE_UDP);
   11946         [ #  # ]:          0 :                 if (mlx5_flow_is_std_vxlan_port(prev_item))
   11947                 :          0 :                         return &graph[MLX5_EXPANSION_STD_VXLAN];
   11948                 :          0 :                 return &graph[MLX5_EXPANSION_L3_VXLAN];
   11949                 :            :         }
   11950                 :            :         return node;
   11951                 :            : }
   11952                 :            : 
   11953                 :            : /* Map of Verbs to Flow priority with 8 Verbs priorities. */
   11954                 :            : static const uint32_t priority_map_3[][MLX5_PRIORITY_MAP_MAX] = {
   11955                 :            :         { 0, 1, 2 }, { 2, 3, 4 }, { 5, 6, 7 },
   11956                 :            : };
   11957                 :            : 
   11958                 :            : /* Map of Verbs to Flow priority with 16 Verbs priorities. */
   11959                 :            : static const uint32_t priority_map_5[][MLX5_PRIORITY_MAP_MAX] = {
   11960                 :            :         { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 },
   11961                 :            :         { 9, 10, 11 }, { 12, 13, 14 },
   11962                 :            : };
   11963                 :            : 
   11964                 :            : /**
   11965                 :            :  * Discover the number of available flow priorities.
   11966                 :            :  *
   11967                 :            :  * @param dev
   11968                 :            :  *   Ethernet device.
   11969                 :            :  *
   11970                 :            :  * @return
   11971                 :            :  *   On success, number of available flow priorities.
   11972                 :            :  *   On failure, a negative errno-style code and rte_errno is set.
   11973                 :            :  */
   11974                 :            : int
   11975                 :          0 : mlx5_flow_discover_priorities(struct rte_eth_dev *dev)
   11976                 :            : {
   11977                 :            :         static const uint16_t vprio[] = {8, 16};
   11978                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
   11979                 :            :         const struct mlx5_flow_driver_ops *fops;
   11980                 :            :         enum mlx5_flow_drv_type type;
   11981                 :            :         int ret;
   11982                 :            : 
   11983                 :            :         type = mlx5_flow_os_get_type();
   11984                 :            :         if (type == MLX5_FLOW_TYPE_MAX) {
   11985                 :            :                 type = MLX5_FLOW_TYPE_VERBS;
   11986   [ #  #  #  # ]:          0 :                 if (priv->sh->cdev->config.devx && priv->sh->config.dv_flow_en)
   11987                 :            :                         type = MLX5_FLOW_TYPE_DV;
   11988                 :            :         }
   11989                 :          0 :         fops = flow_get_drv_ops(type);
   11990         [ #  # ]:          0 :         if (fops->discover_priorities == NULL) {
   11991                 :          0 :                 DRV_LOG(ERR, "Priority discovery not supported");
   11992                 :          0 :                 rte_errno = ENOTSUP;
   11993                 :          0 :                 return -rte_errno;
   11994                 :            :         }
   11995                 :          0 :         ret = fops->discover_priorities(dev, vprio, RTE_DIM(vprio));
   11996         [ #  # ]:          0 :         if (ret < 0)
   11997                 :            :                 return ret;
   11998      [ #  #  # ]:          0 :         switch (ret) {
   11999                 :            :         case 8:
   12000                 :            :                 ret = RTE_DIM(priority_map_3);
   12001                 :            :                 break;
   12002                 :          0 :         case 16:
   12003                 :            :                 ret = RTE_DIM(priority_map_5);
   12004                 :          0 :                 break;
   12005                 :          0 :         default:
   12006                 :          0 :                 rte_errno = ENOTSUP;
   12007                 :          0 :                 DRV_LOG(ERR,
   12008                 :            :                         "port %u maximum priority: %d expected 8/16",
   12009                 :            :                         dev->data->port_id, ret);
   12010                 :          0 :                 return -rte_errno;
   12011                 :            :         }
   12012                 :          0 :         DRV_LOG(INFO, "port %u supported flow priorities:"
   12013                 :            :                 " 0-%d for ingress or egress root table,"
   12014                 :            :                 " 0-%d for non-root table or transfer root table.",
   12015                 :            :                 dev->data->port_id, ret - 2,
   12016                 :            :                 MLX5_NON_ROOT_FLOW_MAX_PRIO - 1);
   12017                 :          0 :         return ret;
   12018                 :            : }
   12019                 :            : 
   12020                 :            : /**
   12021                 :            :  * Adjust flow priority based on the highest layer and the request priority.
   12022                 :            :  *
   12023                 :            :  * @param[in] dev
   12024                 :            :  *   Pointer to the Ethernet device structure.
   12025                 :            :  * @param[in] priority
   12026                 :            :  *   The rule base priority.
   12027                 :            :  * @param[in] subpriority
   12028                 :            :  *   The priority based on the items.
   12029                 :            :  *
   12030                 :            :  * @return
   12031                 :            :  *   The new priority.
   12032                 :            :  */
   12033                 :            : uint32_t
   12034                 :          0 : mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
   12035                 :            :                           uint32_t subpriority)
   12036                 :            : {
   12037                 :            :         uint32_t res = 0;
   12038                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12039                 :            : 
   12040      [ #  #  # ]:          0 :         switch (priv->sh->flow_max_priority) {
   12041                 :          0 :         case RTE_DIM(priority_map_3):
   12042                 :          0 :                 res = priority_map_3[priority][subpriority];
   12043                 :          0 :                 break;
   12044                 :          0 :         case RTE_DIM(priority_map_5):
   12045                 :          0 :                 res = priority_map_5[priority][subpriority];
   12046                 :          0 :                 break;
   12047                 :            :         }
   12048                 :          0 :         return  res;
   12049                 :            : }
   12050                 :            : 
   12051                 :            : /**
   12052                 :            :  * Get the priority for sending traffic to kernel table.
   12053                 :            :  *
   12054                 :            :  * @param[in] dev
   12055                 :            :  *   Pointer to the Ethernet device structure.
   12056                 :            :  *
   12057                 :            :  * @return
   12058                 :            :  *   On success: the value of priority for sending traffic to kernel table
   12059                 :            :  *   On failure: -1
   12060                 :            :  */
   12061                 :            : uint32_t
   12062                 :          0 : mlx5_get_send_to_kernel_priority(struct rte_eth_dev *dev)
   12063                 :            : {
   12064                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12065                 :            :         uint32_t res;
   12066                 :            : 
   12067      [ #  #  # ]:          0 :         switch (priv->sh->flow_max_priority) {
   12068                 :            :         case RTE_DIM(priority_map_5):
   12069                 :            :                 res = 15;
   12070                 :            :                 break;
   12071                 :          0 :         case RTE_DIM(priority_map_3):
   12072                 :            :                 res = 7;
   12073                 :          0 :                 break;
   12074                 :          0 :         default:
   12075                 :          0 :                 DRV_LOG(ERR,
   12076                 :            :                         "port %u maximum priority: %d expected 8/16",
   12077                 :            :                         dev->data->port_id, priv->sh->flow_max_priority);
   12078                 :            :                 res = (uint32_t)-1;
   12079                 :            :         }
   12080                 :          0 :         return res;
   12081                 :            : }
   12082                 :            : 
   12083                 :            : /**
   12084                 :            :  * Get the E-Switch Manager vport id.
   12085                 :            :  *
   12086                 :            :  * @param[in] dev
   12087                 :            :  *   Pointer to the Ethernet device structure.
   12088                 :            :  *
   12089                 :            :  * @return
   12090                 :            :  *   The vport id.
   12091                 :            :  */
   12092                 :          0 : int16_t mlx5_flow_get_esw_manager_vport_id(struct rte_eth_dev *dev)
   12093                 :            : {
   12094                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12095                 :          0 :         struct mlx5_common_device *cdev = priv->sh->cdev;
   12096                 :            : 
   12097                 :            :         /* New FW exposes E-Switch Manager vport ID, can use it directly. */
   12098         [ #  # ]:          0 :         if (cdev->config.hca_attr.esw_mgr_vport_id_valid)
   12099                 :          0 :                 return (int16_t)cdev->config.hca_attr.esw_mgr_vport_id;
   12100                 :            : 
   12101         [ #  # ]:          0 :         if (priv->pci_dev == NULL)
   12102                 :            :                 return 0;
   12103         [ #  # ]:          0 :         switch (priv->pci_dev->id.device_id) {
   12104                 :            :         case PCI_DEVICE_ID_MELLANOX_BLUEFIELD:
   12105                 :            :         case PCI_DEVICE_ID_MELLANOX_BLUEFIELD2:
   12106                 :            :         case PCI_DEVICE_ID_MELLANOX_BLUEFIELD3:
   12107                 :            :         /*
   12108                 :            :          * In old FW which doesn't expose the E-Switch Manager vport ID in the capability,
   12109                 :            :          * only the BF embedded CPUs control the E-Switch Manager port. Hence,
   12110                 :            :          * ECPF vport ID is selected and not the host port (0) in any BF case.
   12111                 :            :          */
   12112                 :            :                 return (int16_t)MLX5_ECPF_VPORT_ID;
   12113                 :          0 :         default:
   12114                 :          0 :                 return MLX5_PF_VPORT_ID;
   12115                 :            :         }
   12116                 :            : }
   12117                 :            : 
   12118                 :            : /**
   12119                 :            :  * Parse item to get the vport id.
   12120                 :            :  *
   12121                 :            :  * @param[in] dev
   12122                 :            :  *   Pointer to the Ethernet device structure.
   12123                 :            :  * @param[in] item
   12124                 :            :  *   The src port id match item.
   12125                 :            :  * @param[out] vport_id
   12126                 :            :  *   Pointer to put the vport id.
   12127                 :            :  * @param[out] all_ports
   12128                 :            :  *   Indicate if the item matches all ports.
   12129                 :            :  * @param[out] error
   12130                 :            :  *   Pointer to error structure.
   12131                 :            :  *
   12132                 :            :  * @return
   12133                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   12134                 :            :  */
   12135                 :          0 : int mlx5_flow_get_item_vport_id(struct rte_eth_dev *dev,
   12136                 :            :                                 const struct rte_flow_item *item,
   12137                 :            :                                 uint16_t *vport_id,
   12138                 :            :                                 bool *all_ports,
   12139                 :            :                                 struct rte_flow_error *error)
   12140                 :            : {
   12141                 :            :         struct mlx5_priv *port_priv;
   12142                 :            :         const struct rte_flow_item_port_id *pid_v = NULL;
   12143                 :            :         const struct rte_flow_item_ethdev *dev_v = NULL;
   12144                 :            :         uint32_t esw_mgr_port;
   12145                 :            :         uint32_t src_port;
   12146                 :            : 
   12147         [ #  # ]:          0 :         if (all_ports)
   12148                 :          0 :                 *all_ports = false;
   12149   [ #  #  #  # ]:          0 :         switch (item->type) {
   12150                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_ID:
   12151                 :          0 :                 pid_v = item->spec;
   12152         [ #  # ]:          0 :                 if (!pid_v)
   12153                 :            :                         return 0;
   12154                 :          0 :                 src_port = pid_v->id;
   12155                 :            :                 esw_mgr_port = MLX5_PORT_ESW_MGR;
   12156                 :          0 :                 break;
   12157                 :          0 :         case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
   12158                 :          0 :                 dev_v = item->spec;
   12159         [ #  # ]:          0 :                 if (!dev_v) {
   12160         [ #  # ]:          0 :                         if (all_ports)
   12161                 :          0 :                                 *all_ports = true;
   12162                 :          0 :                         return 0;
   12163                 :            :                 }
   12164                 :          0 :                 src_port = dev_v->port_id;
   12165                 :            :                 esw_mgr_port = MLX5_REPRESENTED_PORT_ESW_MGR;
   12166                 :          0 :                 break;
   12167                 :            :         case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
   12168                 :            :                 src_port = MLX5_REPRESENTED_PORT_ESW_MGR;
   12169                 :            :                 esw_mgr_port = MLX5_REPRESENTED_PORT_ESW_MGR;
   12170                 :            :                 break;
   12171                 :          0 :         default:
   12172                 :          0 :                 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
   12173                 :            :                                           NULL, "Incorrect item type.");
   12174                 :            :         }
   12175         [ #  # ]:          0 :         if (src_port == esw_mgr_port) {
   12176                 :          0 :                 *vport_id = mlx5_flow_get_esw_manager_vport_id(dev);
   12177                 :            :         } else {
   12178                 :          0 :                 port_priv = mlx5_port_to_eswitch_info(src_port, false);
   12179         [ #  # ]:          0 :                 if (!port_priv)
   12180                 :          0 :                         return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
   12181                 :            :                                                   NULL, "Failed to get port info.");
   12182                 :          0 :                 *vport_id = port_priv->representor_id;
   12183                 :            :         }
   12184                 :            : 
   12185                 :            :         return 0;
   12186                 :            : }
   12187                 :            : 
   12188                 :            : int
   12189                 :          0 : mlx5_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
   12190                 :            :                               uint16_t *proxy_port_id,
   12191                 :            :                               struct rte_flow_error *error)
   12192                 :            : {
   12193                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
   12194                 :            :         uint16_t port_id;
   12195                 :            : 
   12196         [ #  # ]:          0 :         if (!priv->sh->config.dv_esw_en)
   12197                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12198                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12199                 :            :                                           NULL,
   12200                 :            :                                           "unable to provide a proxy port"
   12201                 :            :                                           " without E-Switch configured");
   12202         [ #  # ]:          0 :         if (!priv->master && !priv->representor)
   12203                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12204                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12205                 :            :                                           NULL,
   12206                 :            :                                           "unable to provide a proxy port"
   12207                 :            :                                           " for port which is not a master"
   12208                 :            :                                           " or a representor port");
   12209         [ #  # ]:          0 :         if (priv->master) {
   12210                 :          0 :                 *proxy_port_id = dev->data->port_id;
   12211                 :          0 :                 return 0;
   12212                 :            :         }
   12213         [ #  # ]:          0 :         MLX5_ETH_FOREACH_DEV(port_id, dev->device) {
   12214                 :          0 :                 const struct rte_eth_dev *port_dev = &rte_eth_devices[port_id];
   12215                 :          0 :                 const struct mlx5_priv *port_priv = port_dev->data->dev_private;
   12216                 :            : 
   12217         [ #  # ]:          0 :                 if (port_priv->master &&
   12218         [ #  # ]:          0 :                     port_priv->domain_id == priv->domain_id) {
   12219                 :          0 :                         *proxy_port_id = port_id;
   12220                 :          0 :                         return 0;
   12221                 :            :                 }
   12222                 :            :         }
   12223                 :          0 :         return rte_flow_error_set(error, ENODEV,
   12224                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12225                 :            :                                   NULL, "unable to find a proxy port");
   12226                 :            : }
   12227                 :            : 
   12228                 :            : /**
   12229                 :            :  * Discover IPv6 traffic class ID support in rdma-core and firmware.
   12230                 :            :  *
   12231                 :            :  * @param dev
   12232                 :            :  *   Ethernet device.
   12233                 :            :  *
   12234                 :            :  * @return
   12235                 :            :  *   0, rdma-core is good to work with firmware.
   12236                 :            :  *   -EOPNOTSUPP, rdma-core could not work with new IPv6 TC ID.
   12237                 :            :  */
   12238                 :            : int
   12239                 :          0 : mlx5_flow_discover_ipv6_tc_support(struct rte_eth_dev *dev)
   12240                 :            : {
   12241                 :            :         struct rte_flow_action_set_dscp set_dscp;
   12242                 :            :         struct rte_flow_attr attr;
   12243                 :            :         struct rte_flow_action actions[2];
   12244                 :            :         struct rte_flow_item items[3];
   12245                 :            :         struct rte_flow_error error;
   12246                 :            :         uint32_t flow_idx;
   12247                 :            : 
   12248                 :            :         memset(&attr, 0, sizeof(attr));
   12249                 :            :         memset(actions, 0, sizeof(actions));
   12250                 :            :         memset(items, 0, sizeof(items));
   12251                 :          0 :         attr.group = 1;
   12252                 :          0 :         attr.egress = 1;
   12253                 :          0 :         items[0].type = RTE_FLOW_ITEM_TYPE_ETH;
   12254                 :          0 :         items[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
   12255                 :            :         items[2].type = RTE_FLOW_ITEM_TYPE_END;
   12256                 :            :         /* Random value */
   12257                 :          0 :         set_dscp.dscp = 9;
   12258                 :          0 :         actions[0].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP;
   12259                 :          0 :         actions[0].conf = &set_dscp;
   12260                 :            :         actions[1].type = RTE_FLOW_ACTION_TYPE_END;
   12261                 :            : 
   12262                 :          0 :         flow_idx = mlx5_flow_list_create(dev, MLX5_FLOW_TYPE_GEN, &attr, items,
   12263                 :            :                                          actions, true, &error);
   12264         [ #  # ]:          0 :         if (!flow_idx)
   12265                 :            :                 return -EOPNOTSUPP;
   12266                 :            : 
   12267                 :          0 :         mlx5_flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN, flow_idx);
   12268                 :          0 :         return 0;
   12269                 :            : }
   12270                 :            : 
   12271                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_create_geneve_tlv_parser, 24.03)
   12272                 :            : void *
   12273                 :          0 : rte_pmd_mlx5_create_geneve_tlv_parser(uint16_t port_id,
   12274                 :            :                                       const struct rte_pmd_mlx5_geneve_tlv tlv_list[],
   12275                 :            :                                       uint8_t nb_options)
   12276                 :            : {
   12277                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   12278                 :          0 :         return mlx5_geneve_tlv_parser_create(port_id, tlv_list, nb_options);
   12279                 :            : #else
   12280                 :            :         (void)port_id;
   12281                 :            :         (void)tlv_list;
   12282                 :            :         (void)nb_options;
   12283                 :            :         DRV_LOG(ERR, "%s is not supported.", __func__);
   12284                 :            :         rte_errno = ENOTSUP;
   12285                 :            :         return NULL;
   12286                 :            : #endif
   12287                 :            : }
   12288                 :            : 
   12289                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_destroy_geneve_tlv_parser, 24.03)
   12290                 :            : int
   12291                 :          0 : rte_pmd_mlx5_destroy_geneve_tlv_parser(void *handle)
   12292                 :            : {
   12293                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   12294                 :          0 :         return mlx5_geneve_tlv_parser_destroy(handle);
   12295                 :            : #else
   12296                 :            :         (void)handle;
   12297                 :            :         DRV_LOG(ERR, "%s is not supported.", __func__);
   12298                 :            :         rte_errno = ENOTSUP;
   12299                 :            :         return -rte_errno;
   12300                 :            : #endif
   12301                 :            : }
   12302                 :            : 
   12303                 :            : bool
   12304                 :          0 : mlx5_ctrl_flow_uc_dmac_exists(struct rte_eth_dev *dev, const struct rte_ether_addr *addr)
   12305                 :            : {
   12306                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12307                 :            :         struct mlx5_ctrl_flow_entry *entry;
   12308                 :            :         bool exists = false;
   12309                 :            : 
   12310         [ #  # ]:          0 :         LIST_FOREACH(entry, &priv->hw_ctrl_flows, next) {
   12311   [ #  #  #  # ]:          0 :                 if (entry->info.type == MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC &&
   12312                 :            :                     rte_is_same_ether_addr(addr, &entry->info.uc.dmac)) {
   12313                 :            :                         exists = true;
   12314                 :            :                         break;
   12315                 :            :                 }
   12316                 :            :         }
   12317                 :          0 :         return exists;
   12318                 :            : }
   12319                 :            : 
   12320                 :            : bool
   12321                 :          0 : mlx5_ctrl_flow_uc_dmac_vlan_exists(struct rte_eth_dev *dev,
   12322                 :            :                                    const struct rte_ether_addr *addr,
   12323                 :            :                                    const uint16_t vid)
   12324                 :            : {
   12325                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12326                 :            :         struct mlx5_ctrl_flow_entry *entry;
   12327                 :            :         bool exists = false;
   12328                 :            : 
   12329         [ #  # ]:          0 :         LIST_FOREACH(entry, &priv->hw_ctrl_flows, next) {
   12330   [ #  #  #  # ]:          0 :                 if (entry->info.type == MLX5_CTRL_FLOW_TYPE_DEFAULT_RX_RSS_UNICAST_DMAC_VLAN &&
   12331                 :          0 :                     rte_is_same_ether_addr(addr, &entry->info.uc.dmac) &&
   12332         [ #  # ]:          0 :                     vid == entry->info.uc.vlan) {
   12333                 :            :                         exists = true;
   12334                 :            :                         break;
   12335                 :            :                 }
   12336                 :            :         }
   12337                 :          0 :         return exists;
   12338                 :            : }

Generated by: LCOV version 1.14