LCOV - code coverage report
Current view: top level - drivers/net/mlx5 - mlx5_flow_dv.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 7547 0.0 %
Date: 2024-12-01 18:57:19 Functions: 0 288 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 6059 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2018 Mellanox Technologies, Ltd
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <sys/queue.h>
       6                 :            : #include <stdalign.h>
       7                 :            : #include <stdint.h>
       8                 :            : #include <string.h>
       9                 :            : #include <unistd.h>
      10                 :            : 
      11                 :            : #include <rte_bitops.h>
      12                 :            : #include <rte_common.h>
      13                 :            : #include <rte_ether.h>
      14                 :            : #include <ethdev_driver.h>
      15                 :            : #include <rte_flow.h>
      16                 :            : #include <rte_flow_driver.h>
      17                 :            : #include <rte_malloc.h>
      18                 :            : #include <rte_cycles.h>
      19                 :            : #include <bus_pci_driver.h>
      20                 :            : #include <rte_ip.h>
      21                 :            : #include <rte_gre.h>
      22                 :            : #include <rte_vxlan.h>
      23                 :            : #include <rte_gtp.h>
      24                 :            : #include <rte_eal_paging.h>
      25                 :            : #include <rte_mpls.h>
      26                 :            : #include <rte_mtr.h>
      27                 :            : #include <rte_mtr_driver.h>
      28                 :            : #include <rte_tailq.h>
      29                 :            : 
      30                 :            : #include <mlx5_glue.h>
      31                 :            : #include <mlx5_devx_cmds.h>
      32                 :            : #include <mlx5_prm.h>
      33                 :            : #include <mlx5_malloc.h>
      34                 :            : 
      35                 :            : #include "mlx5_defs.h"
      36                 :            : #include "mlx5.h"
      37                 :            : #include "mlx5_common_os.h"
      38                 :            : #include "mlx5_flow.h"
      39                 :            : #include "mlx5_flow_os.h"
      40                 :            : #include "mlx5_rx.h"
      41                 :            : #include "mlx5_tx.h"
      42                 :            : #include "rte_pmd_mlx5.h"
      43                 :            : 
      44                 :            : #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
      45                 :            : 
      46                 :            : #ifndef HAVE_IBV_FLOW_DEVX_COUNTERS
      47                 :            : #define MLX5DV_FLOW_ACTION_COUNTERS_DEVX 0
      48                 :            : #endif
      49                 :            : 
      50                 :            : #ifndef HAVE_MLX5DV_DR_ESWITCH
      51                 :            : #ifndef MLX5DV_FLOW_TABLE_TYPE_FDB
      52                 :            : #define MLX5DV_FLOW_TABLE_TYPE_FDB 0
      53                 :            : #endif
      54                 :            : #endif
      55                 :            : 
      56                 :            : #ifndef HAVE_MLX5DV_DR
      57                 :            : #define MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL 1
      58                 :            : #endif
      59                 :            : 
      60                 :            : /* VLAN header definitions */
      61                 :            : #define MLX5DV_FLOW_VLAN_PCP_SHIFT 13
      62                 :            : #define MLX5DV_FLOW_VLAN_PCP_MASK (0x7 << MLX5DV_FLOW_VLAN_PCP_SHIFT)
      63                 :            : #define MLX5DV_FLOW_VLAN_VID_MASK 0x0fff
      64                 :            : #define MLX5DV_FLOW_VLAN_PCP_MASK_BE RTE_BE16(MLX5DV_FLOW_VLAN_PCP_MASK)
      65                 :            : #define MLX5DV_FLOW_VLAN_VID_MASK_BE RTE_BE16(MLX5DV_FLOW_VLAN_VID_MASK)
      66                 :            : 
      67                 :            : #define MLX5_ITEM_VALID(item, key_type) \
      68                 :            :         (((MLX5_SET_MATCHER_SW & (key_type)) && !((item)->spec)) || \
      69                 :            :          ((MLX5_SET_MATCHER_HS_V == (key_type)) && !((item)->spec)) || \
      70                 :            :          ((MLX5_SET_MATCHER_HS_M == (key_type)) && !((item)->mask)))
      71                 :            : 
      72                 :            : #define MLX5_ITEM_UPDATE(item, key_type, v, m, gm) \
      73                 :            :         do { \
      74                 :            :                 if ((key_type) == MLX5_SET_MATCHER_SW_V) { \
      75                 :            :                         v = (item)->spec; \
      76                 :            :                         m = (item)->mask ? (item)->mask : (gm); \
      77                 :            :                 } else if ((key_type) == MLX5_SET_MATCHER_HS_V) { \
      78                 :            :                         v = (item)->spec; \
      79                 :            :                         m = (v); \
      80                 :            :                 } else { \
      81                 :            :                         v = (item)->mask ? (item)->mask : (gm); \
      82                 :            :                         m = (v); \
      83                 :            :                 } \
      84                 :            :         } while (0)
      85                 :            : 
      86                 :            : #define CALC_MODI_ID(field, level) \
      87                 :            :         (((level) > 1) ? MLX5_MODI_IN_##field : MLX5_MODI_OUT_##field)
      88                 :            : 
      89                 :            : union flow_dv_attr {
      90                 :            :         struct {
      91                 :            :                 uint32_t valid:1;
      92                 :            :                 uint32_t ipv4:1;
      93                 :            :                 uint32_t ipv6:1;
      94                 :            :                 uint32_t tcp:1;
      95                 :            :                 uint32_t udp:1;
      96                 :            :                 uint32_t reserved:27;
      97                 :            :         };
      98                 :            :         uint32_t attr;
      99                 :            : };
     100                 :            : 
     101                 :            : static int
     102                 :            : flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
     103                 :            :                                         uint32_t port_id);
     104                 :            : static void
     105                 :            : flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss);
     106                 :            : 
     107                 :            : static int
     108                 :            : flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
     109                 :            :                                   uint32_t rix_jump);
     110                 :            : 
     111                 :            : /**
     112                 :            :  * Initialize flow attributes structure according to flow items' types.
     113                 :            :  *
     114                 :            :  * flow_dv_validate() avoids multiple L3/L4 layers cases other than tunnel
     115                 :            :  * mode. For tunnel mode, the items to be modified are the outermost ones.
     116                 :            :  *
     117                 :            :  * @param[in] item
     118                 :            :  *   Pointer to item specification.
     119                 :            :  * @param[out] attr
     120                 :            :  *   Pointer to flow attributes structure.
     121                 :            :  * @param[in] dev_flow
     122                 :            :  *   Pointer to the sub flow.
     123                 :            :  * @param[in] tunnel_decap
     124                 :            :  *   Whether action is after tunnel decapsulation.
     125                 :            :  */
     126                 :            : static void
     127                 :          0 : flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr,
     128                 :            :                   struct mlx5_flow *dev_flow, bool tunnel_decap)
     129                 :            : {
     130                 :          0 :         uint64_t layers = dev_flow->handle->layers;
     131                 :            :         bool tunnel_match = false;
     132                 :            : 
     133                 :            :         /*
     134                 :            :          * If layers is already initialized, it means this dev_flow is the
     135                 :            :          * suffix flow, the layers flags is set by the prefix flow. Need to
     136                 :            :          * use the layer flags from prefix flow as the suffix flow may not
     137                 :            :          * have the user defined items as the flow is split.
     138                 :            :          */
     139         [ #  # ]:          0 :         if (layers) {
     140         [ #  # ]:          0 :                 if (tunnel_decap) {
     141                 :            :                         /*
     142                 :            :                          * If decap action before modify, it means the driver
     143                 :            :                          * should take the inner as outer for the modify actions.
     144                 :            :                          */
     145                 :          0 :                         layers = ((layers >> 6) & MLX5_FLOW_LAYER_OUTER);
     146                 :            :                 }
     147         [ #  # ]:          0 :                 if (layers & MLX5_FLOW_LAYER_OUTER_L3_IPV4)
     148                 :          0 :                         attr->ipv4 = 1;
     149         [ #  # ]:          0 :                 else if (layers & MLX5_FLOW_LAYER_OUTER_L3_IPV6)
     150                 :          0 :                         attr->ipv6 = 1;
     151         [ #  # ]:          0 :                 if (layers & MLX5_FLOW_LAYER_OUTER_L4_TCP)
     152                 :          0 :                         attr->tcp = 1;
     153         [ #  # ]:          0 :                 else if (layers & MLX5_FLOW_LAYER_OUTER_L4_UDP)
     154                 :          0 :                         attr->udp = 1;
     155                 :          0 :                 attr->valid = 1;
     156                 :          0 :                 return;
     157                 :            :         }
     158         [ #  # ]:          0 :         for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
     159                 :            :                 uint8_t next_protocol = 0xff;
     160   [ #  #  #  #  :          0 :                 switch (item->type) {
                   #  # ]
     161                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
     162                 :            :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
     163                 :            :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
     164                 :            :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
     165                 :            :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
     166                 :            :                 case RTE_FLOW_ITEM_TYPE_MPLS:
     167                 :            :                 case RTE_FLOW_ITEM_TYPE_GTP:
     168         [ #  # ]:          0 :                         if (tunnel_decap) {
     169                 :          0 :                                 attr->attr = 0;
     170                 :            :                                 tunnel_match = true;
     171                 :            :                         }
     172                 :            :                         break;
     173                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
     174         [ #  # ]:          0 :                         if (!attr->ipv6)
     175                 :          0 :                                 attr->ipv4 = 1;
     176         [ #  # ]:          0 :                         if (item->mask != NULL &&
     177                 :            :                             ((const struct rte_flow_item_ipv4 *)
     178         [ #  # ]:          0 :                             item->mask)->hdr.next_proto_id)
     179                 :          0 :                                 next_protocol =
     180                 :            :                                     ((const struct rte_flow_item_ipv4 *)
     181                 :          0 :                                       (item->spec))->hdr.next_proto_id &
     182                 :            :                                     ((const struct rte_flow_item_ipv4 *)
     183                 :            :                                       (item->mask))->hdr.next_proto_id;
     184                 :          0 :                         if ((next_protocol == IPPROTO_IPIP ||
     185         [ #  # ]:          0 :                             next_protocol == IPPROTO_IPV6) && tunnel_decap &&
     186         [ #  # ]:          0 :                             !tunnel_match)
     187                 :          0 :                                 attr->attr = 0;
     188                 :            :                         break;
     189                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
     190         [ #  # ]:          0 :                         if (!attr->ipv4)
     191                 :          0 :                                 attr->ipv6 = 1;
     192         [ #  # ]:          0 :                         if (item->mask != NULL &&
     193                 :            :                             ((const struct rte_flow_item_ipv6 *)
     194         [ #  # ]:          0 :                             item->mask)->hdr.proto)
     195                 :          0 :                                 next_protocol =
     196                 :            :                                     ((const struct rte_flow_item_ipv6 *)
     197                 :          0 :                                       (item->spec))->hdr.proto &
     198                 :            :                                     ((const struct rte_flow_item_ipv6 *)
     199                 :            :                                       (item->mask))->hdr.proto;
     200                 :          0 :                         if ((next_protocol == IPPROTO_IPIP ||
     201         [ #  # ]:          0 :                             next_protocol == IPPROTO_IPV6) && tunnel_decap &&
     202         [ #  # ]:          0 :                             !tunnel_match)
     203                 :          0 :                                 attr->attr = 0;
     204                 :            :                         break;
     205                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
     206         [ #  # ]:          0 :                         if (!attr->tcp)
     207                 :          0 :                                 attr->udp = 1;
     208                 :            :                         break;
     209                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
     210         [ #  # ]:          0 :                         if (!attr->udp)
     211                 :          0 :                                 attr->tcp = 1;
     212                 :            :                         break;
     213                 :            :                 default:
     214                 :            :                         break;
     215                 :            :                 }
     216                 :            :         }
     217                 :          0 :         attr->valid = 1;
     218                 :            : }
     219                 :            : 
     220                 :            : struct field_modify_info modify_eth[] = {
     221                 :            :         {4,  0, MLX5_MODI_OUT_DMAC_47_16},
     222                 :            :         {2,  4, MLX5_MODI_OUT_DMAC_15_0},
     223                 :            :         {4,  6, MLX5_MODI_OUT_SMAC_47_16},
     224                 :            :         {2, 10, MLX5_MODI_OUT_SMAC_15_0},
     225                 :            :         {0, 0, 0},
     226                 :            : };
     227                 :            : 
     228                 :            : struct field_modify_info modify_vlan_out_first_vid[] = {
     229                 :            :         /* Size in bits !!! */
     230                 :            :         {12, 0, MLX5_MODI_OUT_FIRST_VID},
     231                 :            :         {0, 0, 0},
     232                 :            : };
     233                 :            : 
     234                 :            : struct field_modify_info modify_ipv4[] = {
     235                 :            :         {1,  1, MLX5_MODI_OUT_IP_DSCP},
     236                 :            :         {1,  8, MLX5_MODI_OUT_IPV4_TTL},
     237                 :            :         {4, 12, MLX5_MODI_OUT_SIPV4},
     238                 :            :         {4, 16, MLX5_MODI_OUT_DIPV4},
     239                 :            :         {0, 0, 0},
     240                 :            : };
     241                 :            : 
     242                 :            : struct field_modify_info modify_ipv6[] = {
     243                 :            :         {1,  0, MLX5_MODI_OUT_IP_DSCP},
     244                 :            :         {1,  7, MLX5_MODI_OUT_IPV6_HOPLIMIT},
     245                 :            :         {4,  8, MLX5_MODI_OUT_SIPV6_127_96},
     246                 :            :         {4, 12, MLX5_MODI_OUT_SIPV6_95_64},
     247                 :            :         {4, 16, MLX5_MODI_OUT_SIPV6_63_32},
     248                 :            :         {4, 20, MLX5_MODI_OUT_SIPV6_31_0},
     249                 :            :         {4, 24, MLX5_MODI_OUT_DIPV6_127_96},
     250                 :            :         {4, 28, MLX5_MODI_OUT_DIPV6_95_64},
     251                 :            :         {4, 32, MLX5_MODI_OUT_DIPV6_63_32},
     252                 :            :         {4, 36, MLX5_MODI_OUT_DIPV6_31_0},
     253                 :            :         {0, 0, 0},
     254                 :            : };
     255                 :            : 
     256                 :            : struct field_modify_info modify_ipv6_traffic_class[] = {
     257                 :            :         {1,  0, MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS},
     258                 :            :         {0, 0, 0},
     259                 :            : };
     260                 :            : 
     261                 :            : struct field_modify_info modify_udp[] = {
     262                 :            :         {2, 0, MLX5_MODI_OUT_UDP_SPORT},
     263                 :            :         {2, 2, MLX5_MODI_OUT_UDP_DPORT},
     264                 :            :         {0, 0, 0},
     265                 :            : };
     266                 :            : 
     267                 :            : struct field_modify_info modify_tcp[] = {
     268                 :            :         {2, 0, MLX5_MODI_OUT_TCP_SPORT},
     269                 :            :         {2, 2, MLX5_MODI_OUT_TCP_DPORT},
     270                 :            :         {4, 4, MLX5_MODI_OUT_TCP_SEQ_NUM},
     271                 :            :         {4, 8, MLX5_MODI_OUT_TCP_ACK_NUM},
     272                 :            :         {0, 0, 0},
     273                 :            : };
     274                 :            : 
     275                 :            : enum mlx5_l3_tunnel_detection {
     276                 :            :         l3_tunnel_none,
     277                 :            :         l3_tunnel_outer,
     278                 :            :         l3_tunnel_inner
     279                 :            : };
     280                 :            : 
     281                 :            : static enum mlx5_l3_tunnel_detection
     282                 :            : mlx5_flow_tunnel_ip_check(const struct rte_flow_item *item __rte_unused,
     283                 :            :                           uint8_t next_protocol, uint64_t item_flags,
     284                 :            :                           uint64_t *l3_tunnel_flag)
     285                 :            : {
     286                 :            :         enum mlx5_l3_tunnel_detection td = l3_tunnel_none;
     287                 :            : 
     288                 :            :         MLX5_ASSERT(item->type == RTE_FLOW_ITEM_TYPE_IPV4 ||
     289                 :            :                     item->type == RTE_FLOW_ITEM_TYPE_IPV6);
     290   [ #  #  #  #  :          0 :         if ((item_flags & MLX5_FLOW_LAYER_OUTER_L3) == 0) {
             #  #  #  # ]
     291   [ #  #  #  #  :          0 :                 switch (next_protocol) {
          #  #  #  #  #  
                #  #  # ]
     292                 :            :                 case IPPROTO_IPIP:
     293                 :            :                         td = l3_tunnel_outer;
     294                 :            :                         *l3_tunnel_flag = MLX5_FLOW_LAYER_IPIP;
     295                 :            :                         break;
     296                 :            :                 case IPPROTO_IPV6:
     297                 :            :                         td = l3_tunnel_outer;
     298                 :            :                         *l3_tunnel_flag = MLX5_FLOW_LAYER_IPV6_ENCAP;
     299                 :            :                         break;
     300                 :            :                 default:
     301                 :            :                         break;
     302                 :            :                 }
     303                 :            :         } else {
     304                 :            :                 td = l3_tunnel_inner;
     305                 :            :                 *l3_tunnel_flag = item->type == RTE_FLOW_ITEM_TYPE_IPV4 ?
     306                 :            :                                   MLX5_FLOW_LAYER_IPIP :
     307                 :            :                                   MLX5_FLOW_LAYER_IPV6_ENCAP;
     308                 :            :         }
     309                 :            :         return td;
     310                 :            : }
     311                 :            : 
     312                 :            : static inline struct mlx5_hlist *
     313                 :          0 : flow_dv_hlist_prepare(struct mlx5_dev_ctx_shared *sh, RTE_ATOMIC(struct mlx5_hlist *) *phl,
     314                 :            :                      const char *name, uint32_t size, bool direct_key,
     315                 :            :                      bool lcores_share, void *ctx,
     316                 :            :                      mlx5_list_create_cb cb_create,
     317                 :            :                      mlx5_list_match_cb cb_match,
     318                 :            :                      mlx5_list_remove_cb cb_remove,
     319                 :            :                      mlx5_list_clone_cb cb_clone,
     320                 :            :                      mlx5_list_clone_free_cb cb_clone_free,
     321                 :            :                      struct rte_flow_error *error)
     322                 :            : {
     323                 :            :         struct mlx5_hlist *hl;
     324                 :            :         struct mlx5_hlist *expected = NULL;
     325                 :            :         char s[MLX5_NAME_SIZE];
     326                 :            : 
     327                 :          0 :         hl = rte_atomic_load_explicit(phl, rte_memory_order_seq_cst);
     328         [ #  # ]:          0 :         if (likely(hl))
     329                 :            :                 return hl;
     330                 :          0 :         snprintf(s, sizeof(s), "%s_%s", sh->ibdev_name, name);
     331                 :          0 :         hl = mlx5_hlist_create(s, size, direct_key, lcores_share,
     332                 :            :                         ctx, cb_create, cb_match, cb_remove, cb_clone,
     333                 :            :                         cb_clone_free);
     334         [ #  # ]:          0 :         if (!hl) {
     335                 :          0 :                 DRV_LOG(ERR, "%s hash creation failed", name);
     336                 :          0 :                 rte_flow_error_set(error, ENOMEM,
     337                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
     338                 :            :                                    "cannot allocate resource memory");
     339                 :          0 :                 return NULL;
     340                 :            :         }
     341         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(phl, &expected, hl,
     342                 :            :                                          rte_memory_order_seq_cst,
     343                 :            :                                          rte_memory_order_seq_cst)) {
     344                 :          0 :                 mlx5_hlist_destroy(hl);
     345                 :          0 :                 hl = rte_atomic_load_explicit(phl, rte_memory_order_seq_cst);
     346                 :            :         }
     347                 :            :         return hl;
     348                 :            : }
     349                 :            : 
     350                 :            : /* Update VLAN's VID/PCP based on input rte_flow_action.
     351                 :            :  *
     352                 :            :  * @param[in] action
     353                 :            :  *   Pointer to struct rte_flow_action.
     354                 :            :  * @param[out] vlan
     355                 :            :  *   Pointer to struct rte_vlan_hdr.
     356                 :            :  */
     357                 :            : static void
     358                 :          0 : mlx5_update_vlan_vid_pcp(const struct rte_flow_action *action,
     359                 :            :                          struct rte_vlan_hdr *vlan)
     360                 :            : {
     361                 :            :         uint16_t vlan_tci;
     362         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) {
     363                 :          0 :                 vlan_tci =
     364                 :            :                     ((const struct rte_flow_action_of_set_vlan_pcp *)
     365                 :          0 :                                                action->conf)->vlan_pcp;
     366                 :          0 :                 vlan_tci = vlan_tci << MLX5DV_FLOW_VLAN_PCP_SHIFT;
     367                 :          0 :                 vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK;
     368                 :          0 :                 vlan->vlan_tci |= vlan_tci;
     369         [ #  # ]:          0 :         } else if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) {
     370                 :          0 :                 vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_VID_MASK;
     371         [ #  # ]:          0 :                 vlan->vlan_tci |= rte_be_to_cpu_16
     372                 :            :                     (((const struct rte_flow_action_of_set_vlan_vid *)
     373                 :            :                                              action->conf)->vlan_vid);
     374                 :            :         }
     375                 :          0 : }
     376                 :            : 
     377                 :            : /**
     378                 :            :  * Convert modify-header action to DV specification.
     379                 :            :  *
     380                 :            :  * Data length of each action is determined by provided field description
     381                 :            :  * and the item mask. Data bit offset and width of each action is determined
     382                 :            :  * by provided item mask.
     383                 :            :  *
     384                 :            :  * @param[in] item
     385                 :            :  *   Pointer to item specification.
     386                 :            :  * @param[in] field
     387                 :            :  *   Pointer to field modification information.
     388                 :            :  *     For MLX5_MODIFICATION_TYPE_SET specifies destination field.
     389                 :            :  *     For MLX5_MODIFICATION_TYPE_ADD specifies destination field.
     390                 :            :  *     For MLX5_MODIFICATION_TYPE_COPY specifies source field.
     391                 :            :  *     For MLX5_MODIFICATION_TYPE_ADD_FIELD specifies source field.
     392                 :            :  * @param[in] dest
     393                 :            :  *   Destination field info for MLX5_MODIFICATION_TYPE_COPY and
     394                 :            :  *   MLX5_MODIFICATION_TYPE_ADD_FIELD in @type.
     395                 :            :  *   Negative offset value sets the same offset as source offset.
     396                 :            :  *   size field is ignored, value is taken from source field.
     397                 :            :  * @param[in,out] resource
     398                 :            :  *   Pointer to the modify-header resource.
     399                 :            :  * @param[in] type
     400                 :            :  *   Type of modification.
     401                 :            :  * @param[out] error
     402                 :            :  *   Pointer to the error structure.
     403                 :            :  *
     404                 :            :  * @return
     405                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     406                 :            :  */
     407                 :            : int
     408                 :          0 : flow_dv_convert_modify_action(struct rte_flow_item *item,
     409                 :            :                               struct field_modify_info *field,
     410                 :            :                               struct field_modify_info *dest,
     411                 :            :                               struct mlx5_flow_dv_modify_hdr_resource *resource,
     412                 :            :                               uint32_t type, struct rte_flow_error *error)
     413                 :            : {
     414                 :          0 :         uint32_t i = resource->actions_num;
     415                 :          0 :         struct mlx5_modification_cmd *actions = resource->actions;
     416                 :            :         uint32_t carry_b = 0;
     417                 :            :         bool to_dest;
     418                 :            : 
     419                 :            :         /*
     420                 :            :          * The item and mask are provided in big-endian format.
     421                 :            :          * The fields should be presented as in big-endian format either.
     422                 :            :          * Mask must be always present, it defines the actual field width.
     423                 :            :          */
     424                 :            :         MLX5_ASSERT(item->mask);
     425                 :            :         MLX5_ASSERT(field->size);
     426                 :          0 :         to_dest = type == MLX5_MODIFICATION_TYPE_COPY ||
     427                 :          0 :                   type == MLX5_MODIFICATION_TYPE_ADD_FIELD;
     428                 :            :         do {
     429                 :            :                 uint32_t size_b;
     430                 :            :                 uint32_t off_b;
     431                 :            :                 uint32_t mask;
     432                 :            :                 uint32_t data;
     433                 :            :                 bool next_field = true;
     434                 :            :                 bool next_dest = true;
     435                 :            : 
     436         [ #  # ]:          0 :                 if (i >= MLX5_MAX_MODIFY_NUM)
     437                 :          0 :                         return rte_flow_error_set(error, EINVAL,
     438                 :            :                                  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
     439                 :            :                                  "too many items to modify");
     440                 :            :                 /* Fetch variable byte size mask from the array. */
     441                 :          0 :                 mask = flow_dv_fetch_field((const uint8_t *)item->mask +
     442                 :          0 :                                            field->offset, field->size);
     443         [ #  # ]:          0 :                 if (!mask) {
     444                 :          0 :                         ++field;
     445                 :            :                         continue;
     446                 :            :                 }
     447   [ #  #  #  # ]:          0 :                 if (to_dest && field->is_flex) {
     448                 :          0 :                         off_b = 32 - field->shift + carry_b - field->size * CHAR_BIT;
     449                 :          0 :                         size_b = field->size * CHAR_BIT - carry_b;
     450                 :            :                 } else {
     451                 :            :                         /* Deduce actual data width in bits from mask value. */
     452                 :          0 :                         off_b = rte_bsf32(mask) + carry_b;
     453                 :          0 :                         size_b = sizeof(uint32_t) * CHAR_BIT -
     454                 :          0 :                                  off_b - rte_clz32(mask);
     455                 :            :                 }
     456                 :            :                 MLX5_ASSERT(size_b);
     457                 :          0 :                 actions[i] = (struct mlx5_modification_cmd) {
     458                 :            :                         .action_type = type,
     459                 :          0 :                         .field = field->id,
     460                 :            :                         .offset = off_b,
     461                 :            :                         .length = (size_b == sizeof(uint32_t) * CHAR_BIT) ?
     462         [ #  # ]:          0 :                                 0 : size_b,
     463                 :            :                 };
     464         [ #  # ]:          0 :                 if (to_dest) {
     465                 :            :                         MLX5_ASSERT(dest);
     466                 :          0 :                         actions[i].dst_field = dest->id;
     467                 :          0 :                         actions[i].dst_offset =
     468         [ #  # ]:          0 :                                 (int)dest->offset < 0 ? off_b : dest->offset;
     469                 :            :                         /* Convert entire record to big-endian format. */
     470         [ #  # ]:          0 :                         actions[i].data1 = rte_cpu_to_be_32(actions[i].data1);
     471                 :            :                         /*
     472                 :            :                          * Destination field overflow. Copy leftovers of
     473                 :            :                          * a source field to the next destination field.
     474                 :            :                          */
     475   [ #  #  #  # ]:          0 :                         if ((size_b > dest->size * CHAR_BIT - dest->offset) &&
     476                 :            :                             dest->size != 0) {
     477                 :          0 :                                 actions[i].length =
     478                 :          0 :                                         dest->size * CHAR_BIT - dest->offset;
     479                 :          0 :                                 carry_b += actions[i].length;
     480                 :          0 :                                 next_field = false;
     481                 :            :                         } else {
     482                 :            :                                 carry_b = 0;
     483                 :            :                         }
     484                 :            :                         /*
     485                 :            :                          * Not enough bits in a source filed to fill a
     486                 :            :                          * destination field. Switch to the next source.
     487                 :            :                          */
     488         [ #  # ]:          0 :                         if ((size_b < dest->size * CHAR_BIT - dest->offset) &&
     489         [ #  # ]:          0 :                             ((size_b == field->size * CHAR_BIT - off_b) ||
     490         [ #  # ]:          0 :                              field->is_flex)) {
     491                 :          0 :                                 actions[i].length = size_b;
     492                 :          0 :                                 dest->offset += actions[i].length;
     493                 :            :                                 next_dest = false;
     494                 :            :                         }
     495                 :            :                 } else {
     496                 :            :                         MLX5_ASSERT(item->spec);
     497                 :          0 :                         data = flow_dv_fetch_field((const uint8_t *)item->spec +
     498                 :            :                                                    field->offset, field->size);
     499                 :            :                         /* Shift out the trailing masked bits from data. */
     500                 :          0 :                         data = (data & mask) >> off_b;
     501         [ #  # ]:          0 :                         if (field->is_flex)
     502                 :          0 :                                 actions[i].offset = 32 - field->shift - field->size * CHAR_BIT;
     503         [ #  # ]:          0 :                         actions[i].data1 = rte_cpu_to_be_32(data);
     504                 :            :                 }
     505                 :            :                 /* Convert entire record to expected big-endian format. */
     506         [ #  # ]:          0 :                 actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
     507         [ #  # ]:          0 :                 if ((!to_dest ||
     508   [ #  #  #  # ]:          0 :                      dest->id != (enum mlx5_modification_field)UINT32_MAX) &&
     509                 :            :                     field->id != (enum mlx5_modification_field)UINT32_MAX)
     510                 :          0 :                         ++i;
     511         [ #  # ]:          0 :                 if (next_dest && to_dest)
     512                 :          0 :                         ++dest;
     513         [ #  # ]:          0 :                 if (next_field)
     514                 :          0 :                         ++field;
     515         [ #  # ]:          0 :         } while (field->size);
     516         [ #  # ]:          0 :         if (resource->actions_num == i)
     517                 :          0 :                 return rte_flow_error_set(error, EINVAL,
     518                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
     519                 :            :                                           "invalid modification flow item");
     520                 :          0 :         resource->actions_num = i;
     521                 :          0 :         return 0;
     522                 :            : }
     523                 :            : 
     524                 :            : /**
     525                 :            :  * Convert modify-header set IPv4 address action to DV specification.
     526                 :            :  *
     527                 :            :  * @param[in,out] resource
     528                 :            :  *   Pointer to the modify-header resource.
     529                 :            :  * @param[in] action
     530                 :            :  *   Pointer to action specification.
     531                 :            :  * @param[out] error
     532                 :            :  *   Pointer to the error structure.
     533                 :            :  *
     534                 :            :  * @return
     535                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     536                 :            :  */
     537                 :            : static int
     538                 :          0 : flow_dv_convert_action_modify_ipv4
     539                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     540                 :            :                          const struct rte_flow_action *action,
     541                 :            :                          struct rte_flow_error *error)
     542                 :            : {
     543                 :          0 :         const struct rte_flow_action_set_ipv4 *conf =
     544                 :            :                 (const struct rte_flow_action_set_ipv4 *)(action->conf);
     545         [ #  # ]:          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV4 };
     546                 :            :         struct rte_flow_item_ipv4 ipv4;
     547                 :            :         struct rte_flow_item_ipv4 ipv4_mask;
     548                 :            : 
     549                 :            :         memset(&ipv4, 0, sizeof(ipv4));
     550                 :            :         memset(&ipv4_mask, 0, sizeof(ipv4_mask));
     551         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC) {
     552                 :          0 :                 ipv4.hdr.src_addr = conf->ipv4_addr;
     553                 :          0 :                 ipv4_mask.hdr.src_addr = rte_flow_item_ipv4_mask.hdr.src_addr;
     554                 :            :         } else {
     555                 :          0 :                 ipv4.hdr.dst_addr = conf->ipv4_addr;
     556                 :          0 :                 ipv4_mask.hdr.dst_addr = rte_flow_item_ipv4_mask.hdr.dst_addr;
     557                 :            :         }
     558                 :          0 :         item.spec = &ipv4;
     559                 :          0 :         item.mask = &ipv4_mask;
     560                 :          0 :         return flow_dv_convert_modify_action(&item, modify_ipv4, NULL, resource,
     561                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     562                 :            : }
     563                 :            : 
     564                 :            : /**
     565                 :            :  * Convert modify-header set IPv6 address action to DV specification.
     566                 :            :  *
     567                 :            :  * @param[in,out] resource
     568                 :            :  *   Pointer to the modify-header resource.
     569                 :            :  * @param[in] action
     570                 :            :  *   Pointer to action specification.
     571                 :            :  * @param[out] error
     572                 :            :  *   Pointer to the error structure.
     573                 :            :  *
     574                 :            :  * @return
     575                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     576                 :            :  */
     577                 :            : static int
     578                 :          0 : flow_dv_convert_action_modify_ipv6
     579                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     580                 :            :                          const struct rte_flow_action *action,
     581                 :            :                          struct rte_flow_error *error)
     582                 :            : {
     583                 :          0 :         const struct rte_flow_action_set_ipv6 *conf =
     584                 :            :                 (const struct rte_flow_action_set_ipv6 *)(action->conf);
     585         [ #  # ]:          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV6 };
     586                 :            :         struct rte_flow_item_ipv6 ipv6;
     587                 :            :         struct rte_flow_item_ipv6 ipv6_mask;
     588                 :            : 
     589                 :            :         memset(&ipv6, 0, sizeof(ipv6));
     590                 :            :         memset(&ipv6_mask, 0, sizeof(ipv6_mask));
     591         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC) {
     592                 :            :                 memcpy(&ipv6.hdr.src_addr, &conf->ipv6_addr,
     593                 :            :                        sizeof(ipv6.hdr.src_addr));
     594                 :            :                 memcpy(&ipv6_mask.hdr.src_addr,
     595                 :            :                        &rte_flow_item_ipv6_mask.hdr.src_addr,
     596                 :            :                        sizeof(ipv6.hdr.src_addr));
     597                 :            :         } else {
     598                 :            :                 memcpy(&ipv6.hdr.dst_addr, &conf->ipv6_addr,
     599                 :            :                        sizeof(ipv6.hdr.dst_addr));
     600                 :            :                 memcpy(&ipv6_mask.hdr.dst_addr,
     601                 :            :                        &rte_flow_item_ipv6_mask.hdr.dst_addr,
     602                 :            :                        sizeof(ipv6.hdr.dst_addr));
     603                 :            :         }
     604                 :          0 :         item.spec = &ipv6;
     605                 :          0 :         item.mask = &ipv6_mask;
     606                 :          0 :         return flow_dv_convert_modify_action(&item, modify_ipv6, NULL, resource,
     607                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     608                 :            : }
     609                 :            : 
     610                 :            : /**
     611                 :            :  * Convert modify-header set MAC address action to DV specification.
     612                 :            :  *
     613                 :            :  * @param[in,out] resource
     614                 :            :  *   Pointer to the modify-header resource.
     615                 :            :  * @param[in] action
     616                 :            :  *   Pointer to action specification.
     617                 :            :  * @param[out] error
     618                 :            :  *   Pointer to the error structure.
     619                 :            :  *
     620                 :            :  * @return
     621                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     622                 :            :  */
     623                 :            : static int
     624                 :          0 : flow_dv_convert_action_modify_mac
     625                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     626                 :            :                          const struct rte_flow_action *action,
     627                 :            :                          struct rte_flow_error *error)
     628                 :            : {
     629                 :          0 :         const struct rte_flow_action_set_mac *conf =
     630                 :            :                 (const struct rte_flow_action_set_mac *)(action->conf);
     631         [ #  # ]:          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_ETH };
     632                 :            :         struct rte_flow_item_eth eth;
     633                 :            :         struct rte_flow_item_eth eth_mask;
     634                 :            : 
     635                 :            :         memset(&eth, 0, sizeof(eth));
     636                 :            :         memset(&eth_mask, 0, sizeof(eth_mask));
     637         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_SET_MAC_SRC) {
     638                 :            :                 memcpy(&eth.hdr.src_addr.addr_bytes, &conf->mac_addr,
     639                 :            :                        sizeof(eth.hdr.src_addr.addr_bytes));
     640                 :            :                 memcpy(&eth_mask.hdr.src_addr.addr_bytes,
     641                 :            :                        &rte_flow_item_eth_mask.hdr.src_addr.addr_bytes,
     642                 :            :                        sizeof(eth_mask.hdr.src_addr.addr_bytes));
     643                 :            :         } else {
     644                 :            :                 memcpy(&eth.hdr.dst_addr.addr_bytes, &conf->mac_addr,
     645                 :            :                        sizeof(eth.hdr.dst_addr.addr_bytes));
     646                 :            :                 memcpy(&eth_mask.hdr.dst_addr.addr_bytes,
     647                 :            :                        &rte_flow_item_eth_mask.hdr.dst_addr.addr_bytes,
     648                 :            :                        sizeof(eth_mask.hdr.dst_addr.addr_bytes));
     649                 :            :         }
     650                 :          0 :         item.spec = &eth;
     651                 :          0 :         item.mask = &eth_mask;
     652                 :          0 :         return flow_dv_convert_modify_action(&item, modify_eth, NULL, resource,
     653                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     654                 :            : }
     655                 :            : 
     656                 :            : /**
     657                 :            :  * Convert modify-header set VLAN VID action to DV specification.
     658                 :            :  *
     659                 :            :  * @param[in,out] resource
     660                 :            :  *   Pointer to the modify-header resource.
     661                 :            :  * @param[in] action
     662                 :            :  *   Pointer to action specification.
     663                 :            :  * @param[out] error
     664                 :            :  *   Pointer to the error structure.
     665                 :            :  *
     666                 :            :  * @return
     667                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     668                 :            :  */
     669                 :            : static int
     670                 :          0 : flow_dv_convert_action_modify_vlan_vid
     671                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     672                 :            :                          const struct rte_flow_action *action,
     673                 :            :                          struct rte_flow_error *error)
     674                 :            : {
     675                 :          0 :         const struct rte_flow_action_of_set_vlan_vid *conf =
     676                 :            :                 (const struct rte_flow_action_of_set_vlan_vid *)(action->conf);
     677                 :          0 :         int i = resource->actions_num;
     678                 :          0 :         struct mlx5_modification_cmd *actions = resource->actions;
     679                 :            :         struct field_modify_info *field = modify_vlan_out_first_vid;
     680                 :            : 
     681         [ #  # ]:          0 :         if (i >= MLX5_MAX_MODIFY_NUM)
     682                 :          0 :                 return rte_flow_error_set(error, EINVAL,
     683                 :            :                          RTE_FLOW_ERROR_TYPE_ACTION, NULL,
     684                 :            :                          "too many items to modify");
     685                 :          0 :         actions[i] = (struct mlx5_modification_cmd) {
     686                 :            :                 .action_type = MLX5_MODIFICATION_TYPE_SET,
     687                 :          0 :                 .field = field->id,
     688                 :          0 :                 .length = field->size,
     689                 :          0 :                 .offset = field->offset,
     690                 :            :         };
     691         [ #  # ]:          0 :         actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
     692                 :          0 :         actions[i].data1 = conf->vlan_vid;
     693                 :          0 :         actions[i].data1 = actions[i].data1 << 16;
     694                 :          0 :         resource->actions_num = ++i;
     695                 :          0 :         return 0;
     696                 :            : }
     697                 :            : 
     698                 :            : /**
     699                 :            :  * Convert modify-header set TP action to DV specification.
     700                 :            :  *
     701                 :            :  * @param[in,out] resource
     702                 :            :  *   Pointer to the modify-header resource.
     703                 :            :  * @param[in] action
     704                 :            :  *   Pointer to action specification.
     705                 :            :  * @param[in] items
     706                 :            :  *   Pointer to rte_flow_item objects list.
     707                 :            :  * @param[in] attr
     708                 :            :  *   Pointer to flow attributes structure.
     709                 :            :  * @param[in] dev_flow
     710                 :            :  *   Pointer to the sub flow.
     711                 :            :  * @param[in] tunnel_decap
     712                 :            :  *   Whether action is after tunnel decapsulation.
     713                 :            :  * @param[out] error
     714                 :            :  *   Pointer to the error structure.
     715                 :            :  *
     716                 :            :  * @return
     717                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     718                 :            :  */
     719                 :            : static int
     720                 :          0 : flow_dv_convert_action_modify_tp
     721                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     722                 :            :                          const struct rte_flow_action *action,
     723                 :            :                          const struct rte_flow_item *items,
     724                 :            :                          union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
     725                 :            :                          bool tunnel_decap, struct rte_flow_error *error)
     726                 :            : {
     727                 :          0 :         const struct rte_flow_action_set_tp *conf =
     728                 :            :                 (const struct rte_flow_action_set_tp *)(action->conf);
     729                 :            :         struct rte_flow_item item;
     730                 :            :         struct rte_flow_item_udp udp;
     731                 :            :         struct rte_flow_item_udp udp_mask;
     732                 :            :         struct rte_flow_item_tcp tcp;
     733                 :            :         struct rte_flow_item_tcp tcp_mask;
     734                 :            :         struct field_modify_info *field;
     735                 :            : 
     736         [ #  # ]:          0 :         if (!attr->valid)
     737                 :          0 :                 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
     738         [ #  # ]:          0 :         if (attr->udp) {
     739                 :            :                 memset(&udp, 0, sizeof(udp));
     740                 :            :                 memset(&udp_mask, 0, sizeof(udp_mask));
     741         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC) {
     742                 :          0 :                         udp.hdr.src_port = conf->port;
     743                 :          0 :                         udp_mask.hdr.src_port =
     744                 :            :                                         rte_flow_item_udp_mask.hdr.src_port;
     745                 :            :                 } else {
     746                 :          0 :                         udp.hdr.dst_port = conf->port;
     747                 :          0 :                         udp_mask.hdr.dst_port =
     748                 :            :                                         rte_flow_item_udp_mask.hdr.dst_port;
     749                 :            :                 }
     750                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_UDP;
     751                 :          0 :                 item.spec = &udp;
     752                 :          0 :                 item.mask = &udp_mask;
     753                 :            :                 field = modify_udp;
     754                 :            :         } else {
     755                 :            :                 MLX5_ASSERT(attr->tcp);
     756                 :            :                 memset(&tcp, 0, sizeof(tcp));
     757                 :            :                 memset(&tcp_mask, 0, sizeof(tcp_mask));
     758         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC) {
     759                 :          0 :                         tcp.hdr.src_port = conf->port;
     760                 :          0 :                         tcp_mask.hdr.src_port =
     761                 :            :                                         rte_flow_item_tcp_mask.hdr.src_port;
     762                 :            :                 } else {
     763                 :          0 :                         tcp.hdr.dst_port = conf->port;
     764                 :          0 :                         tcp_mask.hdr.dst_port =
     765                 :            :                                         rte_flow_item_tcp_mask.hdr.dst_port;
     766                 :            :                 }
     767                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_TCP;
     768                 :          0 :                 item.spec = &tcp;
     769                 :          0 :                 item.mask = &tcp_mask;
     770                 :            :                 field = modify_tcp;
     771                 :            :         }
     772                 :          0 :         return flow_dv_convert_modify_action(&item, field, NULL, resource,
     773                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     774                 :            : }
     775                 :            : 
     776                 :            : /**
     777                 :            :  * Convert modify-header set TTL action to DV specification.
     778                 :            :  *
     779                 :            :  * @param[in,out] resource
     780                 :            :  *   Pointer to the modify-header resource.
     781                 :            :  * @param[in] action
     782                 :            :  *   Pointer to action specification.
     783                 :            :  * @param[in] items
     784                 :            :  *   Pointer to rte_flow_item objects list.
     785                 :            :  * @param[in] attr
     786                 :            :  *   Pointer to flow attributes structure.
     787                 :            :  * @param[in] dev_flow
     788                 :            :  *   Pointer to the sub flow.
     789                 :            :  * @param[in] tunnel_decap
     790                 :            :  *   Whether action is after tunnel decapsulation.
     791                 :            :  * @param[out] error
     792                 :            :  *   Pointer to the error structure.
     793                 :            :  *
     794                 :            :  * @return
     795                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     796                 :            :  */
     797                 :            : static int
     798                 :          0 : flow_dv_convert_action_modify_ttl
     799                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     800                 :            :                          const struct rte_flow_action *action,
     801                 :            :                          const struct rte_flow_item *items,
     802                 :            :                          union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
     803                 :            :                          bool tunnel_decap, struct rte_flow_error *error)
     804                 :            : {
     805                 :          0 :         const struct rte_flow_action_set_ttl *conf =
     806                 :            :                 (const struct rte_flow_action_set_ttl *)(action->conf);
     807                 :            :         struct rte_flow_item item;
     808                 :            :         struct rte_flow_item_ipv4 ipv4;
     809                 :            :         struct rte_flow_item_ipv4 ipv4_mask;
     810                 :            :         struct rte_flow_item_ipv6 ipv6;
     811                 :            :         struct rte_flow_item_ipv6 ipv6_mask;
     812                 :            :         struct field_modify_info *field;
     813                 :            : 
     814         [ #  # ]:          0 :         if (!attr->valid)
     815                 :          0 :                 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
     816         [ #  # ]:          0 :         if (attr->ipv4) {
     817                 :            :                 memset(&ipv4, 0, sizeof(ipv4));
     818                 :            :                 memset(&ipv4_mask, 0, sizeof(ipv4_mask));
     819                 :          0 :                 ipv4.hdr.time_to_live = conf->ttl_value;
     820                 :          0 :                 ipv4_mask.hdr.time_to_live = 0xFF;
     821                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_IPV4;
     822                 :          0 :                 item.spec = &ipv4;
     823                 :          0 :                 item.mask = &ipv4_mask;
     824                 :            :                 field = modify_ipv4;
     825                 :            :         } else {
     826                 :            :                 MLX5_ASSERT(attr->ipv6);
     827                 :            :                 memset(&ipv6, 0, sizeof(ipv6));
     828                 :            :                 memset(&ipv6_mask, 0, sizeof(ipv6_mask));
     829                 :          0 :                 ipv6.hdr.hop_limits = conf->ttl_value;
     830                 :          0 :                 ipv6_mask.hdr.hop_limits = 0xFF;
     831                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_IPV6;
     832                 :          0 :                 item.spec = &ipv6;
     833                 :          0 :                 item.mask = &ipv6_mask;
     834                 :            :                 field = modify_ipv6;
     835                 :            :         }
     836                 :          0 :         return flow_dv_convert_modify_action(&item, field, NULL, resource,
     837                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
     838                 :            : }
     839                 :            : 
     840                 :            : /**
     841                 :            :  * Convert modify-header decrement TTL action to DV specification.
     842                 :            :  *
     843                 :            :  * @param[in,out] resource
     844                 :            :  *   Pointer to the modify-header resource.
     845                 :            :  * @param[in] action
     846                 :            :  *   Pointer to action specification.
     847                 :            :  * @param[in] items
     848                 :            :  *   Pointer to rte_flow_item objects list.
     849                 :            :  * @param[in] attr
     850                 :            :  *   Pointer to flow attributes structure.
     851                 :            :  * @param[in] dev_flow
     852                 :            :  *   Pointer to the sub flow.
     853                 :            :  * @param[in] tunnel_decap
     854                 :            :  *   Whether action is after tunnel decapsulation.
     855                 :            :  * @param[out] error
     856                 :            :  *   Pointer to the error structure.
     857                 :            :  *
     858                 :            :  * @return
     859                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     860                 :            :  */
     861                 :            : static int
     862                 :          0 : flow_dv_convert_action_modify_dec_ttl
     863                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     864                 :            :                          const struct rte_flow_item *items,
     865                 :            :                          union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
     866                 :            :                          bool tunnel_decap, struct rte_flow_error *error)
     867                 :            : {
     868                 :            :         struct rte_flow_item item;
     869                 :            :         struct rte_flow_item_ipv4 ipv4;
     870                 :            :         struct rte_flow_item_ipv4 ipv4_mask;
     871                 :            :         struct rte_flow_item_ipv6 ipv6;
     872                 :            :         struct rte_flow_item_ipv6 ipv6_mask;
     873                 :            :         struct field_modify_info *field;
     874                 :            : 
     875         [ #  # ]:          0 :         if (!attr->valid)
     876                 :          0 :                 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
     877         [ #  # ]:          0 :         if (attr->ipv4) {
     878                 :            :                 memset(&ipv4, 0, sizeof(ipv4));
     879                 :            :                 memset(&ipv4_mask, 0, sizeof(ipv4_mask));
     880                 :          0 :                 ipv4.hdr.time_to_live = 0xFF;
     881                 :          0 :                 ipv4_mask.hdr.time_to_live = 0xFF;
     882                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_IPV4;
     883                 :          0 :                 item.spec = &ipv4;
     884                 :          0 :                 item.mask = &ipv4_mask;
     885                 :            :                 field = modify_ipv4;
     886                 :            :         } else {
     887                 :            :                 MLX5_ASSERT(attr->ipv6);
     888                 :            :                 memset(&ipv6, 0, sizeof(ipv6));
     889                 :            :                 memset(&ipv6_mask, 0, sizeof(ipv6_mask));
     890                 :          0 :                 ipv6.hdr.hop_limits = 0xFF;
     891                 :          0 :                 ipv6_mask.hdr.hop_limits = 0xFF;
     892                 :          0 :                 item.type = RTE_FLOW_ITEM_TYPE_IPV6;
     893                 :          0 :                 item.spec = &ipv6;
     894                 :          0 :                 item.mask = &ipv6_mask;
     895                 :            :                 field = modify_ipv6;
     896                 :            :         }
     897                 :          0 :         return flow_dv_convert_modify_action(&item, field, NULL, resource,
     898                 :            :                                              MLX5_MODIFICATION_TYPE_ADD, error);
     899                 :            : }
     900                 :            : 
     901                 :            : /**
     902                 :            :  * Convert modify-header increment/decrement TCP Sequence number
     903                 :            :  * to DV specification.
     904                 :            :  *
     905                 :            :  * @param[in,out] resource
     906                 :            :  *   Pointer to the modify-header resource.
     907                 :            :  * @param[in] action
     908                 :            :  *   Pointer to action specification.
     909                 :            :  * @param[out] error
     910                 :            :  *   Pointer to the error structure.
     911                 :            :  *
     912                 :            :  * @return
     913                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     914                 :            :  */
     915                 :            : static int
     916                 :          0 : flow_dv_convert_action_modify_tcp_seq
     917                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     918                 :            :                          const struct rte_flow_action *action,
     919                 :            :                          struct rte_flow_error *error)
     920                 :            : {
     921                 :          0 :         const rte_be32_t *conf = (const rte_be32_t *)(action->conf);
     922         [ #  # ]:          0 :         uint64_t value = rte_be_to_cpu_32(*conf);
     923                 :            :         struct rte_flow_item item;
     924                 :            :         struct rte_flow_item_tcp tcp;
     925                 :            :         struct rte_flow_item_tcp tcp_mask;
     926                 :            : 
     927                 :            :         memset(&tcp, 0, sizeof(tcp));
     928                 :            :         memset(&tcp_mask, 0, sizeof(tcp_mask));
     929         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ)
     930                 :            :                 /*
     931                 :            :                  * The HW has no decrement operation, only increment operation.
     932                 :            :                  * To simulate decrement X from Y using increment operation
     933                 :            :                  * we need to add UINT32_MAX X times to Y.
     934                 :            :                  * Each adding of UINT32_MAX decrements Y by 1.
     935                 :            :                  */
     936                 :          0 :                 value *= UINT32_MAX;
     937         [ #  # ]:          0 :         tcp.hdr.sent_seq = rte_cpu_to_be_32((uint32_t)value);
     938                 :          0 :         tcp_mask.hdr.sent_seq = RTE_BE32(UINT32_MAX);
     939                 :          0 :         item.type = RTE_FLOW_ITEM_TYPE_TCP;
     940                 :          0 :         item.spec = &tcp;
     941                 :          0 :         item.mask = &tcp_mask;
     942                 :          0 :         return flow_dv_convert_modify_action(&item, modify_tcp, NULL, resource,
     943                 :            :                                              MLX5_MODIFICATION_TYPE_ADD, error);
     944                 :            : }
     945                 :            : 
     946                 :            : /**
     947                 :            :  * Convert modify-header increment/decrement TCP Acknowledgment number
     948                 :            :  * to DV specification.
     949                 :            :  *
     950                 :            :  * @param[in,out] resource
     951                 :            :  *   Pointer to the modify-header resource.
     952                 :            :  * @param[in] action
     953                 :            :  *   Pointer to action specification.
     954                 :            :  * @param[out] error
     955                 :            :  *   Pointer to the error structure.
     956                 :            :  *
     957                 :            :  * @return
     958                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     959                 :            :  */
     960                 :            : static int
     961                 :          0 : flow_dv_convert_action_modify_tcp_ack
     962                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
     963                 :            :                          const struct rte_flow_action *action,
     964                 :            :                          struct rte_flow_error *error)
     965                 :            : {
     966                 :          0 :         const rte_be32_t *conf = (const rte_be32_t *)(action->conf);
     967         [ #  # ]:          0 :         uint64_t value = rte_be_to_cpu_32(*conf);
     968                 :            :         struct rte_flow_item item;
     969                 :            :         struct rte_flow_item_tcp tcp;
     970                 :            :         struct rte_flow_item_tcp tcp_mask;
     971                 :            : 
     972                 :            :         memset(&tcp, 0, sizeof(tcp));
     973                 :            :         memset(&tcp_mask, 0, sizeof(tcp_mask));
     974         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK)
     975                 :            :                 /*
     976                 :            :                  * The HW has no decrement operation, only increment operation.
     977                 :            :                  * To simulate decrement X from Y using increment operation
     978                 :            :                  * we need to add UINT32_MAX X times to Y.
     979                 :            :                  * Each adding of UINT32_MAX decrements Y by 1.
     980                 :            :                  */
     981                 :          0 :                 value *= UINT32_MAX;
     982         [ #  # ]:          0 :         tcp.hdr.recv_ack = rte_cpu_to_be_32((uint32_t)value);
     983                 :          0 :         tcp_mask.hdr.recv_ack = RTE_BE32(UINT32_MAX);
     984                 :          0 :         item.type = RTE_FLOW_ITEM_TYPE_TCP;
     985                 :          0 :         item.spec = &tcp;
     986                 :          0 :         item.mask = &tcp_mask;
     987                 :          0 :         return flow_dv_convert_modify_action(&item, modify_tcp, NULL, resource,
     988                 :            :                                              MLX5_MODIFICATION_TYPE_ADD, error);
     989                 :            : }
     990                 :            : 
     991                 :            : enum mlx5_modification_field reg_to_field[] = {
     992                 :            :         [REG_NON] = MLX5_MODI_OUT_NONE,
     993                 :            :         [REG_A] = MLX5_MODI_META_DATA_REG_A,
     994                 :            :         [REG_B] = MLX5_MODI_META_DATA_REG_B,
     995                 :            :         [REG_C_0] = MLX5_MODI_META_REG_C_0,
     996                 :            :         [REG_C_1] = MLX5_MODI_META_REG_C_1,
     997                 :            :         [REG_C_2] = MLX5_MODI_META_REG_C_2,
     998                 :            :         [REG_C_3] = MLX5_MODI_META_REG_C_3,
     999                 :            :         [REG_C_4] = MLX5_MODI_META_REG_C_4,
    1000                 :            :         [REG_C_5] = MLX5_MODI_META_REG_C_5,
    1001                 :            :         [REG_C_6] = MLX5_MODI_META_REG_C_6,
    1002                 :            :         [REG_C_7] = MLX5_MODI_META_REG_C_7,
    1003                 :            :         [REG_C_8] = MLX5_MODI_META_REG_C_8,
    1004                 :            :         [REG_C_9] = MLX5_MODI_META_REG_C_9,
    1005                 :            :         [REG_C_10] = MLX5_MODI_META_REG_C_10,
    1006                 :            :         [REG_C_11] = MLX5_MODI_META_REG_C_11,
    1007                 :            : };
    1008                 :            : 
    1009                 :            : const size_t mlx5_mod_reg_size = RTE_DIM(reg_to_field);
    1010                 :            : 
    1011                 :            : /**
    1012                 :            :  * Convert register set to DV specification.
    1013                 :            :  *
    1014                 :            :  * @param[in,out] resource
    1015                 :            :  *   Pointer to the modify-header resource.
    1016                 :            :  * @param[in] action
    1017                 :            :  *   Pointer to action specification.
    1018                 :            :  * @param[out] error
    1019                 :            :  *   Pointer to the error structure.
    1020                 :            :  *
    1021                 :            :  * @return
    1022                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1023                 :            :  */
    1024                 :            : static int
    1025                 :          0 : flow_dv_convert_action_set_reg
    1026                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
    1027                 :            :                          const struct rte_flow_action *action,
    1028                 :            :                          struct rte_flow_error *error)
    1029                 :            : {
    1030                 :          0 :         const struct mlx5_rte_flow_action_set_tag *conf = action->conf;
    1031                 :          0 :         struct mlx5_modification_cmd *actions = resource->actions;
    1032                 :          0 :         uint32_t i = resource->actions_num;
    1033                 :            : 
    1034         [ #  # ]:          0 :         if (i >= MLX5_MAX_MODIFY_NUM)
    1035                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1036                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1037                 :            :                                           "too many items to modify");
    1038                 :            :         MLX5_ASSERT(conf->id != REG_NON);
    1039                 :            :         MLX5_ASSERT(conf->id < (enum modify_reg)RTE_DIM(reg_to_field));
    1040                 :          0 :         actions[i] = (struct mlx5_modification_cmd) {
    1041                 :            :                 .action_type = MLX5_MODIFICATION_TYPE_SET,
    1042                 :          0 :                 .field = reg_to_field[conf->id],
    1043                 :          0 :                 .offset = conf->offset,
    1044                 :          0 :                 .length = conf->length,
    1045                 :            :         };
    1046         [ #  # ]:          0 :         actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
    1047         [ #  # ]:          0 :         actions[i].data1 = rte_cpu_to_be_32(conf->data);
    1048                 :            :         ++i;
    1049                 :          0 :         resource->actions_num = i;
    1050                 :          0 :         return 0;
    1051                 :            : }
    1052                 :            : 
    1053                 :            : /**
    1054                 :            :  * Convert SET_TAG action to DV specification.
    1055                 :            :  *
    1056                 :            :  * @param[in] dev
    1057                 :            :  *   Pointer to the rte_eth_dev structure.
    1058                 :            :  * @param[in,out] resource
    1059                 :            :  *   Pointer to the modify-header resource.
    1060                 :            :  * @param[in] conf
    1061                 :            :  *   Pointer to action specification.
    1062                 :            :  * @param[out] error
    1063                 :            :  *   Pointer to the error structure.
    1064                 :            :  *
    1065                 :            :  * @return
    1066                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1067                 :            :  */
    1068                 :            : static int
    1069                 :          0 : flow_dv_convert_action_set_tag
    1070                 :            :                         (struct rte_eth_dev *dev,
    1071                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    1072                 :            :                          const struct rte_flow_action_set_tag *conf,
    1073                 :            :                          struct rte_flow_error *error)
    1074                 :            : {
    1075         [ #  # ]:          0 :         rte_be32_t data = rte_cpu_to_be_32(conf->data);
    1076         [ #  # ]:          0 :         rte_be32_t mask = rte_cpu_to_be_32(conf->mask);
    1077                 :          0 :         struct rte_flow_item item = {
    1078                 :            :                 .spec = &data,
    1079                 :            :                 .mask = &mask,
    1080                 :            :         };
    1081                 :          0 :         struct field_modify_info reg_c_x[] = {
    1082                 :            :                 [1] = {0, 0, 0},
    1083                 :            :         };
    1084                 :            :         enum mlx5_modification_field reg_type;
    1085                 :            :         int ret;
    1086                 :            : 
    1087                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, conf->index, error);
    1088         [ #  # ]:          0 :         if (ret < 0)
    1089                 :            :                 return ret;
    1090                 :            :         MLX5_ASSERT(ret != REG_NON);
    1091                 :            :         MLX5_ASSERT((unsigned int)ret < RTE_DIM(reg_to_field));
    1092                 :          0 :         reg_type = reg_to_field[ret];
    1093                 :            :         MLX5_ASSERT(reg_type > 0);
    1094                 :          0 :         reg_c_x[0] = (struct field_modify_info){4, 0, reg_type};
    1095                 :          0 :         return flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource,
    1096                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
    1097                 :            : }
    1098                 :            : 
    1099                 :            : /**
    1100                 :            :  * Convert internal COPY_REG action to DV specification.
    1101                 :            :  *
    1102                 :            :  * @param[in] dev
    1103                 :            :  *   Pointer to the rte_eth_dev structure.
    1104                 :            :  * @param[in,out] res
    1105                 :            :  *   Pointer to the modify-header resource.
    1106                 :            :  * @param[in] action
    1107                 :            :  *   Pointer to action specification.
    1108                 :            :  * @param[out] error
    1109                 :            :  *   Pointer to the error structure.
    1110                 :            :  *
    1111                 :            :  * @return
    1112                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1113                 :            :  */
    1114                 :            : static int
    1115                 :          0 : flow_dv_convert_action_copy_mreg(struct rte_eth_dev *dev,
    1116                 :            :                                  struct mlx5_flow_dv_modify_hdr_resource *res,
    1117                 :            :                                  const struct rte_flow_action *action,
    1118                 :            :                                  struct rte_flow_error *error)
    1119                 :            : {
    1120                 :          0 :         const struct mlx5_flow_action_copy_mreg *conf = action->conf;
    1121                 :          0 :         rte_be32_t mask = RTE_BE32(UINT32_MAX);
    1122                 :          0 :         struct rte_flow_item item = {
    1123                 :            :                 .spec = NULL,
    1124                 :            :                 .mask = &mask,
    1125                 :            :         };
    1126                 :          0 :         struct field_modify_info reg_src[] = {
    1127                 :          0 :                 {4, 0, reg_to_field[conf->src]},
    1128                 :            :                 {0, 0, 0},
    1129                 :            :         };
    1130                 :          0 :         struct field_modify_info reg_dst = {
    1131                 :            :                 .offset = 0,
    1132                 :          0 :                 .id = reg_to_field[conf->dst],
    1133                 :            :         };
    1134                 :            :         /* Adjust reg_c[0] usage according to reported mask. */
    1135   [ #  #  #  # ]:          0 :         if (conf->dst == REG_C_0 || conf->src == REG_C_0) {
    1136                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    1137                 :          0 :                 uint32_t reg_c0 = priv->sh->dv_regc0_mask;
    1138                 :            : 
    1139                 :            :                 MLX5_ASSERT(reg_c0);
    1140                 :            :                 MLX5_ASSERT(priv->sh->config.dv_xmeta_en !=
    1141                 :            :                             MLX5_XMETA_MODE_LEGACY);
    1142         [ #  # ]:          0 :                 if (conf->dst == REG_C_0) {
    1143                 :            :                         /* Copy to reg_c[0], within mask only. */
    1144                 :          0 :                         reg_dst.offset = rte_bsf32(reg_c0);
    1145         [ #  # ]:          0 :                         mask = rte_cpu_to_be_32(reg_c0 >> reg_dst.offset);
    1146                 :            :                 } else {
    1147                 :            :                         reg_dst.offset = 0;
    1148         [ #  # ]:          0 :                         mask = rte_cpu_to_be_32(reg_c0);
    1149                 :            :                 }
    1150                 :            :         }
    1151                 :          0 :         return flow_dv_convert_modify_action(&item,
    1152                 :            :                                              reg_src, &reg_dst, res,
    1153                 :            :                                              MLX5_MODIFICATION_TYPE_COPY,
    1154                 :            :                                              error);
    1155                 :            : }
    1156                 :            : 
    1157                 :            : /**
    1158                 :            :  * Convert MARK action to DV specification. This routine is used
    1159                 :            :  * in extensive metadata only and requires metadata register to be
    1160                 :            :  * handled. In legacy mode hardware tag resource is engaged.
    1161                 :            :  *
    1162                 :            :  * @param[in] dev
    1163                 :            :  *   Pointer to the rte_eth_dev structure.
    1164                 :            :  * @param[in] conf
    1165                 :            :  *   Pointer to MARK action specification.
    1166                 :            :  * @param[in,out] resource
    1167                 :            :  *   Pointer to the modify-header resource.
    1168                 :            :  * @param[out] error
    1169                 :            :  *   Pointer to the error structure.
    1170                 :            :  *
    1171                 :            :  * @return
    1172                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1173                 :            :  */
    1174                 :            : static int
    1175                 :          0 : flow_dv_convert_action_mark(struct rte_eth_dev *dev,
    1176                 :            :                             const struct rte_flow_action_mark *conf,
    1177                 :            :                             struct mlx5_flow_dv_modify_hdr_resource *resource,
    1178                 :            :                             struct rte_flow_error *error)
    1179                 :            : {
    1180                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1181         [ #  # ]:          0 :         rte_be32_t mask = rte_cpu_to_be_32(MLX5_FLOW_MARK_MASK &
    1182                 :            :                                            priv->sh->dv_mark_mask);
    1183         [ #  # ]:          0 :         rte_be32_t data = rte_cpu_to_be_32(conf->id) & mask;
    1184                 :          0 :         struct rte_flow_item item = {
    1185                 :            :                 .spec = &data,
    1186                 :            :                 .mask = &mask,
    1187                 :            :         };
    1188                 :          0 :         struct field_modify_info reg_c_x[] = {
    1189                 :            :                 [1] = {0, 0, 0},
    1190                 :            :         };
    1191                 :            :         int reg;
    1192                 :            : 
    1193         [ #  # ]:          0 :         if (!mask)
    1194                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1195                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    1196                 :            :                                           NULL, "zero mark action mask");
    1197                 :          0 :         reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    1198         [ #  # ]:          0 :         if (reg < 0)
    1199                 :            :                 return reg;
    1200                 :            :         MLX5_ASSERT(reg > 0);
    1201         [ #  # ]:          0 :         if (reg == REG_C_0) {
    1202         [ #  # ]:          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
    1203                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
    1204                 :            : 
    1205         [ #  # ]:          0 :                 data = rte_cpu_to_be_32(rte_cpu_to_be_32(data) << shl_c0);
    1206         [ #  # ]:          0 :                 mask = rte_cpu_to_be_32(mask) & msk_c0;
    1207         [ #  # ]:          0 :                 mask = rte_cpu_to_be_32(mask << shl_c0);
    1208                 :            :         }
    1209                 :          0 :         reg_c_x[0] = (struct field_modify_info){4, 0, reg_to_field[reg]};
    1210                 :          0 :         return flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource,
    1211                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
    1212                 :            : }
    1213                 :            : 
    1214                 :            : /**
    1215                 :            :  * Get metadata register index for specified steering domain.
    1216                 :            :  *
    1217                 :            :  * @param[in] dev
    1218                 :            :  *   Pointer to the rte_eth_dev structure.
    1219                 :            :  * @param[in] attr
    1220                 :            :  *   Attributes of flow to determine steering domain.
    1221                 :            :  * @param[out] error
    1222                 :            :  *   Pointer to the error structure.
    1223                 :            :  *
    1224                 :            :  * @return
    1225                 :            :  *   positive index on success, a negative errno value otherwise
    1226                 :            :  *   and rte_errno is set.
    1227                 :            :  */
    1228                 :            : static enum modify_reg
    1229                 :          0 : flow_dv_get_metadata_reg(struct rte_eth_dev *dev,
    1230                 :            :                          const struct rte_flow_attr *attr,
    1231                 :            :                          struct rte_flow_error *error)
    1232                 :            : {
    1233                 :            :         int reg =
    1234         [ #  # ]:          0 :                 mlx5_flow_get_reg_id(dev, attr->transfer ?
    1235                 :          0 :                                           MLX5_METADATA_FDB :
    1236         [ #  # ]:          0 :                                             attr->egress ?
    1237                 :            :                                             MLX5_METADATA_TX :
    1238                 :            :                                             MLX5_METADATA_RX, 0, error);
    1239         [ #  # ]:          0 :         if (reg < 0)
    1240                 :          0 :                 return rte_flow_error_set(error,
    1241                 :            :                                           ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
    1242                 :            :                                           NULL, "unavailable "
    1243                 :            :                                           "metadata register");
    1244                 :          0 :         return reg;
    1245                 :            : }
    1246                 :            : 
    1247                 :            : /**
    1248                 :            :  * Convert SET_META action to DV specification.
    1249                 :            :  *
    1250                 :            :  * @param[in] dev
    1251                 :            :  *   Pointer to the rte_eth_dev structure.
    1252                 :            :  * @param[in,out] resource
    1253                 :            :  *   Pointer to the modify-header resource.
    1254                 :            :  * @param[in] attr
    1255                 :            :  *   Attributes of flow that includes this item.
    1256                 :            :  * @param[in] conf
    1257                 :            :  *   Pointer to action specification.
    1258                 :            :  * @param[out] error
    1259                 :            :  *   Pointer to the error structure.
    1260                 :            :  *
    1261                 :            :  * @return
    1262                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1263                 :            :  */
    1264                 :            : static int
    1265                 :          0 : flow_dv_convert_action_set_meta
    1266                 :            :                         (struct rte_eth_dev *dev,
    1267                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    1268                 :            :                          const struct rte_flow_attr *attr,
    1269                 :            :                          const struct rte_flow_action_set_meta *conf,
    1270                 :            :                          struct rte_flow_error *error)
    1271                 :            : {
    1272         [ #  # ]:          0 :         uint32_t mask = rte_cpu_to_be_32(conf->mask);
    1273         [ #  # ]:          0 :         uint32_t data = rte_cpu_to_be_32(conf->data) & mask;
    1274                 :          0 :         struct rte_flow_item item = {
    1275                 :            :                 .spec = &data,
    1276                 :            :                 .mask = &mask,
    1277                 :            :         };
    1278                 :          0 :         struct field_modify_info reg_c_x[] = {
    1279                 :            :                 [1] = {0, 0, 0},
    1280                 :            :         };
    1281                 :          0 :         int reg = flow_dv_get_metadata_reg(dev, attr, error);
    1282                 :            : 
    1283         [ #  # ]:          0 :         if (reg < 0)
    1284                 :            :                 return reg;
    1285                 :            :         MLX5_ASSERT(reg != REG_NON);
    1286         [ #  # ]:          0 :         if (reg == REG_C_0) {
    1287                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    1288         [ #  # ]:          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
    1289                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
    1290                 :            : 
    1291         [ #  # ]:          0 :                 data = rte_cpu_to_be_32(rte_cpu_to_be_32(data) << shl_c0);
    1292         [ #  # ]:          0 :                 mask = rte_cpu_to_be_32(mask) & msk_c0;
    1293         [ #  # ]:          0 :                 mask = rte_cpu_to_be_32(mask << shl_c0);
    1294                 :            :         }
    1295                 :          0 :         reg_c_x[0] = (struct field_modify_info){4, 0, reg_to_field[reg]};
    1296                 :            :         /* The routine expects parameters in memory as big-endian ones. */
    1297                 :          0 :         return flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource,
    1298                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
    1299                 :            : }
    1300                 :            : 
    1301                 :            : /**
    1302                 :            :  * Convert modify-header set IPv4 DSCP action to DV specification.
    1303                 :            :  *
    1304                 :            :  * @param[in,out] resource
    1305                 :            :  *   Pointer to the modify-header resource.
    1306                 :            :  * @param[in] action
    1307                 :            :  *   Pointer to action specification.
    1308                 :            :  * @param[out] error
    1309                 :            :  *   Pointer to the error structure.
    1310                 :            :  *
    1311                 :            :  * @return
    1312                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1313                 :            :  */
    1314                 :            : static int
    1315                 :          0 : flow_dv_convert_action_modify_ipv4_dscp
    1316                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
    1317                 :            :                          const struct rte_flow_action *action,
    1318                 :            :                          struct rte_flow_error *error)
    1319                 :            : {
    1320                 :          0 :         const struct rte_flow_action_set_dscp *conf =
    1321                 :            :                 (const struct rte_flow_action_set_dscp *)(action->conf);
    1322                 :          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV4 };
    1323                 :            :         struct rte_flow_item_ipv4 ipv4;
    1324                 :            :         struct rte_flow_item_ipv4 ipv4_mask;
    1325                 :            : 
    1326                 :            :         memset(&ipv4, 0, sizeof(ipv4));
    1327                 :            :         memset(&ipv4_mask, 0, sizeof(ipv4_mask));
    1328                 :          0 :         ipv4.hdr.type_of_service = conf->dscp;
    1329                 :          0 :         ipv4_mask.hdr.type_of_service = RTE_IPV4_HDR_DSCP_MASK >> 2;
    1330                 :          0 :         item.spec = &ipv4;
    1331                 :          0 :         item.mask = &ipv4_mask;
    1332                 :          0 :         return flow_dv_convert_modify_action(&item, modify_ipv4, NULL, resource,
    1333                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
    1334                 :            : }
    1335                 :            : 
    1336                 :            : /**
    1337                 :            :  * Convert modify-header set IPv6 DSCP action to DV specification.
    1338                 :            :  *
    1339                 :            :  * @param[in,out] resource
    1340                 :            :  *   Pointer to the modify-header resource.
    1341                 :            :  * @param[in] action
    1342                 :            :  *   Pointer to action specification.
    1343                 :            :  * @param[out] error
    1344                 :            :  *   Pointer to the error structure.
    1345                 :            :  *
    1346                 :            :  * @return
    1347                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1348                 :            :  */
    1349                 :            : static int
    1350                 :          0 : flow_dv_convert_action_modify_ipv6_dscp
    1351                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
    1352                 :            :                          const struct rte_flow_action *action,
    1353                 :            :                          uint32_t ipv6_tc_off,
    1354                 :            :                          struct rte_flow_error *error)
    1355                 :            : {
    1356                 :          0 :         const struct rte_flow_action_set_dscp *conf =
    1357                 :            :                 (const struct rte_flow_action_set_dscp *)(action->conf);
    1358         [ #  # ]:          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV6 };
    1359                 :            :         struct rte_flow_item_ipv6 ipv6;
    1360                 :            :         struct rte_flow_item_ipv6 ipv6_mask;
    1361                 :            :         struct field_modify_info *modify_info;
    1362                 :            : 
    1363                 :            :         memset(&ipv6, 0, sizeof(ipv6));
    1364                 :            :         memset(&ipv6_mask, 0, sizeof(ipv6_mask));
    1365                 :            :         /*
    1366                 :            :          * Even though the DSCP bits offset of IPv6 is not byte aligned,
    1367                 :            :          * rdma-core only accept the DSCP bits byte aligned start from
    1368                 :            :          * bit 0 to 5 as to be compatible with IPv4. No need to shift the
    1369                 :            :          * bits in IPv6 case as rdma-core requires byte aligned value.
    1370                 :            :          * IPv6 DSCP uses OUT_IPV6_TRAFFIC_CLASS as ID but it starts from 2
    1371                 :            :          * bits left. Shift the mask left for IPv6 DSCP. Do it here because
    1372                 :            :          * it's needed to distinguish DSCP from ECN in data field construct
    1373                 :            :          */
    1374                 :          0 :         ipv6.hdr.vtc_flow = conf->dscp << ipv6_tc_off;
    1375                 :          0 :         ipv6_mask.hdr.vtc_flow = RTE_IPV6_HDR_DSCP_MASK >> (22 - ipv6_tc_off);
    1376                 :          0 :         item.spec = &ipv6;
    1377                 :          0 :         item.mask = &ipv6_mask;
    1378         [ #  # ]:          0 :         if (ipv6_tc_off)
    1379                 :            :                 modify_info = modify_ipv6_traffic_class;
    1380                 :            :         else
    1381                 :            :                 modify_info = modify_ipv6;
    1382                 :          0 :         return flow_dv_convert_modify_action(&item, modify_info, NULL, resource,
    1383                 :            :                                              MLX5_MODIFICATION_TYPE_SET, error);
    1384                 :            : }
    1385                 :            : 
    1386                 :            : int
    1387                 :          0 : mlx5_flow_item_field_width(struct rte_eth_dev *dev,
    1388                 :            :                            enum rte_flow_field_id field, int inherit,
    1389                 :            :                            const struct rte_flow_attr *attr,
    1390                 :            :                            struct rte_flow_error *error)
    1391                 :            : {
    1392                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1393                 :            : 
    1394   [ #  #  #  #  :          0 :         switch (field) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1395                 :            :         case RTE_FLOW_FIELD_START:
    1396                 :            :                 return 32;
    1397                 :          0 :         case RTE_FLOW_FIELD_MAC_DST:
    1398                 :            :         case RTE_FLOW_FIELD_MAC_SRC:
    1399                 :          0 :                 return 48;
    1400                 :          0 :         case RTE_FLOW_FIELD_VLAN_TYPE:
    1401                 :          0 :                 return 16;
    1402                 :          0 :         case RTE_FLOW_FIELD_VLAN_ID:
    1403                 :          0 :                 return 12;
    1404                 :          0 :         case RTE_FLOW_FIELD_MAC_TYPE:
    1405                 :          0 :                 return 16;
    1406                 :          0 :         case RTE_FLOW_FIELD_IPV4_DSCP:
    1407                 :          0 :                 return 6;
    1408                 :          0 :         case RTE_FLOW_FIELD_IPV4_TTL:
    1409                 :            :         case RTE_FLOW_FIELD_IPV4_PROTO:
    1410                 :          0 :                 return 8;
    1411                 :            :         case RTE_FLOW_FIELD_IPV4_SRC:
    1412                 :            :         case RTE_FLOW_FIELD_IPV4_DST:
    1413                 :            :                 return 32;
    1414                 :          0 :         case RTE_FLOW_FIELD_IPV6_DSCP:
    1415                 :          0 :                 return 6;
    1416                 :          0 :         case RTE_FLOW_FIELD_IPV6_FLOW_LABEL:
    1417                 :          0 :                 return 20;
    1418                 :          0 :         case RTE_FLOW_FIELD_IPV6_TRAFFIC_CLASS:
    1419                 :            :         case RTE_FLOW_FIELD_IPV6_HOPLIMIT:
    1420                 :            :         case RTE_FLOW_FIELD_IPV6_PROTO:
    1421                 :          0 :                 return 8;
    1422                 :          0 :         case RTE_FLOW_FIELD_IPV6_SRC:
    1423                 :            :         case RTE_FLOW_FIELD_IPV6_DST:
    1424                 :          0 :                 return 128;
    1425                 :          0 :         case RTE_FLOW_FIELD_TCP_PORT_SRC:
    1426                 :            :         case RTE_FLOW_FIELD_TCP_PORT_DST:
    1427                 :          0 :                 return 16;
    1428                 :            :         case RTE_FLOW_FIELD_TCP_SEQ_NUM:
    1429                 :            :         case RTE_FLOW_FIELD_TCP_ACK_NUM:
    1430                 :            :                 return 32;
    1431                 :          0 :         case RTE_FLOW_FIELD_TCP_FLAGS:
    1432                 :          0 :                 return 9;
    1433                 :          0 :         case RTE_FLOW_FIELD_UDP_PORT_SRC:
    1434                 :            :         case RTE_FLOW_FIELD_UDP_PORT_DST:
    1435                 :          0 :                 return 16;
    1436                 :          0 :         case RTE_FLOW_FIELD_VXLAN_VNI:
    1437                 :            :         case RTE_FLOW_FIELD_GENEVE_VNI:
    1438                 :          0 :                 return 24;
    1439                 :          0 :         case RTE_FLOW_FIELD_VXLAN_LAST_RSVD:
    1440                 :          0 :                 return 8;
    1441                 :            :         case RTE_FLOW_FIELD_GTP_TEID:
    1442                 :            :         case RTE_FLOW_FIELD_MPLS:
    1443                 :            :         case RTE_FLOW_FIELD_TAG:
    1444                 :            :         case RTE_FLOW_FIELD_ESP_SPI:
    1445                 :            :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    1446                 :            :                 return 32;
    1447                 :          0 :         case RTE_FLOW_FIELD_ESP_PROTO:
    1448                 :          0 :                 return 8;
    1449                 :          0 :         case RTE_FLOW_FIELD_MARK:
    1450                 :          0 :                 return rte_popcount32(priv->sh->dv_mark_mask);
    1451                 :          0 :         case RTE_FLOW_FIELD_META:
    1452                 :          0 :                 return (flow_dv_get_metadata_reg(dev, attr, error) == REG_C_0) ?
    1453         [ #  # ]:          0 :                         rte_popcount32(priv->sh->dv_meta_mask) : 32;
    1454                 :          0 :         case RTE_FLOW_FIELD_POINTER:
    1455                 :            :         case RTE_FLOW_FIELD_VALUE:
    1456                 :          0 :                 return inherit < 0 ? 0 : inherit;
    1457                 :          0 :         case RTE_FLOW_FIELD_IPV4_ECN:
    1458                 :            :         case RTE_FLOW_FIELD_IPV6_ECN:
    1459                 :            :         case RTE_FLOW_FIELD_METER_COLOR:
    1460                 :          0 :                 return 2;
    1461                 :            :         case RTE_FLOW_FIELD_HASH_RESULT:
    1462                 :            :                 return 32;
    1463                 :          0 :         default:
    1464                 :            :                 MLX5_ASSERT(false);
    1465                 :            :         }
    1466                 :          0 :         return 0;
    1467                 :            : }
    1468                 :            : 
    1469                 :            : static __rte_always_inline uint8_t
    1470                 :            : flow_modify_info_mask_8(uint32_t length, uint32_t off)
    1471                 :            : {
    1472                 :          0 :         return (0xffu >> (8 - length)) << off;
    1473                 :            : }
    1474                 :            : 
    1475                 :            : static __rte_always_inline uint16_t
    1476                 :            : flow_modify_info_mask_16(uint32_t length, uint32_t off)
    1477                 :            : {
    1478   [ #  #  #  #  :          0 :         return rte_cpu_to_be_16((0xffffu >> (16 - length)) << off);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1479                 :            : }
    1480                 :            : 
    1481                 :            : static __rte_always_inline uint32_t
    1482                 :            : flow_modify_info_mask_32(uint32_t length, uint32_t off)
    1483                 :            : {
    1484   [ #  #  #  #  :          0 :         return rte_cpu_to_be_32((0xffffffffu >> (32 - length)) << off);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1485                 :            : }
    1486                 :            : 
    1487                 :            : static __rte_always_inline uint32_t
    1488                 :            : flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mask)
    1489                 :            : {
    1490                 :          0 :         uint32_t mask = (0xffffffffu >> (32 - length)) << off;
    1491                 :          0 :         return rte_cpu_to_be_32(mask & post_mask);
    1492                 :            : }
    1493                 :            : 
    1494                 :            : static __rte_always_inline enum mlx5_modification_field
    1495                 :            : mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
    1496                 :            : {
    1497                 :          0 :         return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
    1498                 :            : }
    1499                 :            : 
    1500                 :            : static __rte_always_inline int
    1501                 :            : flow_geneve_opt_modi_field_get(struct mlx5_priv *priv,
    1502                 :            :                                const struct rte_flow_field_data *data)
    1503                 :            : {
    1504                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    1505                 :          0 :         return mlx5_geneve_opt_modi_field_get(priv, data);
    1506                 :            : #else
    1507                 :            :         (void)priv;
    1508                 :            :         (void)data;
    1509                 :            :         DRV_LOG(ERR, "GENEVE option modification is not supported.");
    1510                 :            :         rte_errno = ENOTSUP;
    1511                 :            :         return -rte_errno;
    1512                 :            : #endif
    1513                 :            : }
    1514                 :            : 
    1515                 :            : static void
    1516                 :          0 : mlx5_modify_flex_item(const struct rte_eth_dev *dev,
    1517                 :            :                       const struct mlx5_flex_item *flex,
    1518                 :            :                       const struct rte_flow_field_data *data,
    1519                 :            :                       struct field_modify_info *info,
    1520                 :            :                       uint32_t *mask, uint32_t width)
    1521                 :            : {
    1522                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1523                 :          0 :         struct mlx5_hca_flex_attr *attr = &priv->sh->cdev->config.hca_attr.flex;
    1524                 :            :         uint32_t i, j;
    1525                 :            :         int id = 0;
    1526                 :          0 :         uint32_t pos = 0;
    1527                 :            :         const struct mlx5_flex_pattern_field *map;
    1528                 :          0 :         uint32_t offset = data->offset;
    1529                 :            :         uint32_t width_left = width;
    1530                 :            :         uint32_t cur_width = 0;
    1531                 :            :         uint32_t tmp_ofs;
    1532                 :            :         uint32_t idx = 0;
    1533                 :            :         struct field_modify_info tmp;
    1534                 :            :         int tmp_id;
    1535                 :            : 
    1536         [ #  # ]:          0 :         if (!attr->query_match_sample_info) {
    1537                 :          0 :                 DRV_LOG(ERR, "FW doesn't support modify field with flex item.");
    1538                 :          0 :                 return;
    1539                 :            :         }
    1540                 :            :         /*
    1541                 :            :          * search for the mapping instance until Accumulated width is no
    1542                 :            :          * less than data->offset.
    1543                 :            :          */
    1544         [ #  # ]:          0 :         for (i = 0; i < flex->mapnum; i++) {
    1545         [ #  # ]:          0 :                 if (flex->map[i].width + pos > data->offset)
    1546                 :            :                         break;
    1547                 :          0 :                 pos += flex->map[i].width;
    1548                 :            :         }
    1549         [ #  # ]:          0 :         if (i >= flex->mapnum)
    1550                 :            :                 return;
    1551         [ #  # ]:          0 :         tmp_ofs = pos < data->offset ? data->offset - pos : 0;
    1552   [ #  #  #  # ]:          0 :         for (j = i; i < flex->mapnum && width_left > 0; ) {
    1553                 :          0 :                 map = flex->map + i;
    1554                 :          0 :                 id = mlx5_flex_get_sample_id(flex, i, &pos, false);
    1555         [ #  # ]:          0 :                 if (id == -1) {
    1556                 :          0 :                         i++;
    1557                 :            :                         /* All left length is dummy */
    1558         [ #  # ]:          0 :                         if (pos >= data->offset + width)
    1559                 :            :                                 return;
    1560                 :          0 :                         cur_width = map->width;
    1561                 :            :                 /* One mapping instance covers the whole width. */
    1562         [ #  # ]:          0 :                 } else if (pos + map->width >= (data->offset + width)) {
    1563                 :            :                         cur_width = width_left;
    1564                 :            :                 } else {
    1565                 :          0 :                         cur_width = cur_width + map->width - tmp_ofs;
    1566                 :          0 :                         pos += map->width;
    1567                 :            :                         /*
    1568                 :            :                          * Continue to search next until:
    1569                 :            :                          * 1. Another flex parser ID.
    1570                 :            :                          * 2. Width has been covered.
    1571                 :            :                          */
    1572         [ #  # ]:          0 :                         for (j = i + 1; j < flex->mapnum; j++) {
    1573                 :          0 :                                 tmp_id = mlx5_flex_get_sample_id(flex, j, &pos, false);
    1574         [ #  # ]:          0 :                                 if (tmp_id == -1) {
    1575                 :            :                                         i = j;
    1576                 :          0 :                                         pos -= flex->map[j].width;
    1577                 :          0 :                                         break;
    1578                 :            :                                 }
    1579   [ #  #  #  # ]:          0 :                                 if (id >= (int)flex->devx_fp->num_samples ||
    1580         [ #  # ]:          0 :                                     id >= MLX5_GRAPH_NODE_SAMPLE_NUM ||
    1581         [ #  # ]:          0 :                                     tmp_id >= (int)flex->devx_fp->num_samples ||
    1582                 :            :                                     tmp_id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
    1583                 :            :                                         return;
    1584                 :          0 :                                 if (flex->devx_fp->sample_info[id].modify_field_id !=
    1585         [ #  # ]:          0 :                                     flex->devx_fp->sample_info[tmp_id].modify_field_id ||
    1586                 :          0 :                                     flex->map[j].shift != flex->map[j - 1].width +
    1587         [ #  # ]:          0 :                                                           flex->map[j - 1].shift) {
    1588                 :            :                                         i = j;
    1589                 :            :                                         break;
    1590                 :            :                                 }
    1591         [ #  # ]:          0 :                                 if ((pos + flex->map[j].width) >= (data->offset + width)) {
    1592                 :            :                                         cur_width = width_left;
    1593                 :            :                                         break;
    1594                 :            :                                 }
    1595                 :          0 :                                 pos += flex->map[j].width;
    1596                 :          0 :                                 cur_width += flex->map[j].width;
    1597                 :            :                         }
    1598                 :            :                 }
    1599         [ #  # ]:          0 :                 if (cur_width > width_left)
    1600                 :            :                         cur_width = width_left;
    1601   [ #  #  #  #  :          0 :                 else if (cur_width < width_left && (j == flex->mapnum || i == flex->mapnum))
                   #  # ]
    1602                 :            :                         return;
    1603                 :            : 
    1604                 :            :                 MLX5_ASSERT(id < (int)flex->devx_fp->num_samples);
    1605   [ #  #  #  # ]:          0 :                 if (id >= (int)flex->devx_fp->num_samples || id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
    1606                 :            :                         return;
    1607                 :            :                 /* Use invalid entry as placeholder for DUMMY mapping. */
    1608                 :          0 :                 info[idx] = (struct field_modify_info){cur_width / CHAR_BIT, offset / CHAR_BIT,
    1609         [ #  # ]:          0 :                              id == -1 ? MLX5_MODI_INVALID :
    1610                 :            :                              (enum mlx5_modification_field)
    1611                 :          0 :                              flex->devx_fp->sample_info[id].modify_field_id,
    1612                 :          0 :                              map->shift + tmp_ofs, 1};
    1613                 :          0 :                 offset += cur_width;
    1614                 :          0 :                 width_left -= cur_width;
    1615         [ #  # ]:          0 :                 if (!mask) {
    1616                 :          0 :                         info[idx].offset = (32 - cur_width - map->shift - tmp_ofs);
    1617                 :          0 :                         info[idx].size = cur_width / CHAR_BIT + info[idx].offset / CHAR_BIT;
    1618                 :            :                 }
    1619                 :            :                 cur_width = 0;
    1620                 :            :                 tmp_ofs = 0;
    1621                 :          0 :                 idx++;
    1622                 :            :         }
    1623         [ #  # ]:          0 :         if (unlikely(width_left > 0)) {
    1624                 :            :                 MLX5_ASSERT(false);
    1625                 :            :                 return;
    1626                 :            :         }
    1627         [ #  # ]:          0 :         if (mask)
    1628                 :          0 :                 memset(mask, 0xff, data->offset / CHAR_BIT + width / CHAR_BIT);
    1629                 :            :         /* Re-order the info to follow IPv6 address. */
    1630         [ #  # ]:          0 :         for (i = 0; i < idx / 2; i++) {
    1631                 :          0 :                 tmp = info[i];
    1632                 :            :                 MLX5_ASSERT(info[i].id);
    1633                 :            :                 MLX5_ASSERT(info[idx - 1 - i].id);
    1634                 :          0 :                 info[i] = info[idx - 1 - i];
    1635                 :          0 :                 info[idx - 1 - i] = tmp;
    1636                 :            :         }
    1637                 :            : }
    1638                 :            : 
    1639                 :            : static inline bool
    1640                 :            : mlx5_dv_modify_ipv6_traffic_class_supported(struct mlx5_priv *priv)
    1641                 :            : {
    1642                 :          0 :         return priv->sh->phdev->config.ipv6_tc_fallback == MLX5_IPV6_TC_OK;
    1643                 :            : }
    1644                 :            : 
    1645                 :            : void
    1646                 :          0 : mlx5_flow_field_id_to_modify_info
    1647                 :            :                 (const struct rte_flow_field_data *data,
    1648                 :            :                  struct field_modify_info *info, uint32_t *mask,
    1649                 :            :                  uint32_t width, struct rte_eth_dev *dev,
    1650                 :            :                  const struct rte_flow_attr *attr, struct rte_flow_error *error)
    1651                 :            : {
    1652                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1653                 :            :         enum mlx5_modification_field modi_id;
    1654                 :            :         uint32_t idx = 0;
    1655                 :            :         uint32_t off_be = 0;
    1656                 :            :         uint32_t length = 0;
    1657                 :            : 
    1658   [ #  #  #  #  :          0 :         switch ((int)data->field) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1659                 :            :         case RTE_FLOW_FIELD_START:
    1660                 :            :                 /* not supported yet */
    1661                 :            :                 MLX5_ASSERT(false);
    1662                 :            :                 break;
    1663                 :          0 :         case RTE_FLOW_FIELD_MAC_DST:
    1664                 :            :                 MLX5_ASSERT(data->offset + width <= 48);
    1665                 :          0 :                 off_be = 48 - (data->offset + width);
    1666         [ #  # ]:          0 :                 if (off_be < 16) {
    1667         [ #  # ]:          0 :                         modi_id = CALC_MODI_ID(DMAC_15_0, data->level);
    1668                 :          0 :                         info[idx] = (struct field_modify_info){2, 4, modi_id};
    1669         [ #  # ]:          0 :                         length = off_be + width <= 16 ? width : 16 - off_be;
    1670         [ #  # ]:          0 :                         if (mask)
    1671                 :          0 :                                 mask[1] = flow_modify_info_mask_16(length,
    1672                 :            :                                                                    off_be);
    1673                 :            :                         else
    1674                 :          0 :                                 info[idx].offset = off_be;
    1675                 :          0 :                         width -= length;
    1676         [ #  # ]:          0 :                         if (!width)
    1677                 :            :                                 break;
    1678                 :            :                         off_be = 0;
    1679                 :            :                         idx++;
    1680                 :            :                 } else {
    1681                 :          0 :                         off_be -= 16;
    1682                 :            :                 }
    1683         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(DMAC_47_16, data->level);
    1684                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1685         [ #  # ]:          0 :                 if (mask)
    1686                 :          0 :                         mask[0] = flow_modify_info_mask_32(width, off_be);
    1687                 :            :                 else
    1688                 :          0 :                         info[idx].offset = off_be;
    1689                 :            :                 break;
    1690                 :          0 :         case RTE_FLOW_FIELD_MAC_SRC:
    1691                 :            :                 MLX5_ASSERT(data->offset + width <= 48);
    1692                 :          0 :                 off_be = 48 - (data->offset + width);
    1693         [ #  # ]:          0 :                 if (off_be < 16) {
    1694         [ #  # ]:          0 :                         modi_id = CALC_MODI_ID(SMAC_15_0, data->level);
    1695                 :          0 :                         info[idx] = (struct field_modify_info){2, 4, modi_id};
    1696         [ #  # ]:          0 :                         length = off_be + width <= 16 ? width : 16 - off_be;
    1697         [ #  # ]:          0 :                         if (mask)
    1698                 :          0 :                                 mask[1] = flow_modify_info_mask_16(length,
    1699                 :            :                                                                    off_be);
    1700                 :            :                         else
    1701                 :          0 :                                 info[idx].offset = off_be;
    1702                 :          0 :                         width -= length;
    1703         [ #  # ]:          0 :                         if (!width)
    1704                 :            :                                 break;
    1705                 :            :                         off_be = 0;
    1706                 :            :                         idx++;
    1707                 :            :                 } else {
    1708                 :          0 :                         off_be -= 16;
    1709                 :            :                 }
    1710         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(SMAC_47_16, data->level);
    1711                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1712         [ #  # ]:          0 :                 if (mask)
    1713                 :          0 :                         mask[0] = flow_modify_info_mask_32(width, off_be);
    1714                 :            :                 else
    1715                 :          0 :                         info[idx].offset = off_be;
    1716                 :            :                 break;
    1717                 :            :         case RTE_FLOW_FIELD_VLAN_TYPE:
    1718                 :            :                 /* not supported yet */
    1719                 :            :                 break;
    1720                 :          0 :         case RTE_FLOW_FIELD_VLAN_ID:
    1721                 :            :                 MLX5_ASSERT(data->offset + width <= 12);
    1722                 :          0 :                 off_be = 12 - (data->offset + width);
    1723                 :          0 :                 info[idx] = (struct field_modify_info){2, 0,
    1724                 :            :                                         MLX5_MODI_OUT_FIRST_VID};
    1725         [ #  # ]:          0 :                 if (mask)
    1726                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1727                 :            :                 else
    1728                 :          0 :                         info[idx].offset = off_be;
    1729                 :            :                 break;
    1730                 :          0 :         case RTE_FLOW_FIELD_MAC_TYPE:
    1731                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1732                 :          0 :                 off_be = 16 - (data->offset + width);
    1733         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(ETHERTYPE, data->level);
    1734                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1735         [ #  # ]:          0 :                 if (mask)
    1736                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1737                 :            :                 else
    1738                 :          0 :                         info[idx].offset = off_be;
    1739                 :            :                 break;
    1740                 :          0 :         case RTE_FLOW_FIELD_IPV4_IHL:
    1741                 :            :                 MLX5_ASSERT(data->offset + width <= 4);
    1742                 :          0 :                 off_be = 4 - (data->offset + width);
    1743         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_IHL, data->level);
    1744                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1745         [ #  # ]:          0 :                 if (mask)
    1746                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1747                 :            :                 else
    1748                 :          0 :                         info[idx].offset = off_be;
    1749                 :            :                 break;
    1750                 :          0 :         case RTE_FLOW_FIELD_IPV4_DSCP:
    1751                 :            :                 MLX5_ASSERT(data->offset + width <= 6);
    1752                 :          0 :                 off_be = 6 - (data->offset + width);
    1753         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IP_DSCP, data->level);
    1754                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1755         [ #  # ]:          0 :                 if (mask)
    1756                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1757                 :            :                 else
    1758                 :          0 :                         info[idx].offset = off_be;
    1759                 :            :                 break;
    1760                 :          0 :         case RTE_FLOW_FIELD_IPV4_TOTAL_LEN:
    1761                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1762                 :          0 :                 off_be = 16 - (data->offset + width);
    1763         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_TOTAL_LEN, data->level);
    1764                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1765         [ #  # ]:          0 :                 if (mask)
    1766                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1767                 :            :                 else
    1768                 :          0 :                         info[idx].offset = off_be;
    1769                 :            :                 break;
    1770                 :          0 :         case RTE_FLOW_FIELD_IPV4_TTL:
    1771                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1772                 :          0 :                 off_be = 8 - (data->offset + width);
    1773         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_TTL, data->level);
    1774                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1775         [ #  # ]:          0 :                 if (mask)
    1776                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1777                 :            :                 else
    1778                 :          0 :                         info[idx].offset = off_be;
    1779                 :            :                 break;
    1780                 :          0 :         case RTE_FLOW_FIELD_IPV4_SRC:
    1781                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1782                 :          0 :                 off_be = 32 - (data->offset + width);
    1783         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(SIPV4, data->level);
    1784                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1785         [ #  # ]:          0 :                 if (mask)
    1786                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1787                 :            :                 else
    1788                 :          0 :                         info[idx].offset = off_be;
    1789                 :            :                 break;
    1790                 :          0 :         case RTE_FLOW_FIELD_IPV4_DST:
    1791                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1792                 :          0 :                 off_be = 32 - (data->offset + width);
    1793         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(DIPV4, data->level);
    1794                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1795         [ #  # ]:          0 :                 if (mask)
    1796                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1797                 :            :                 else
    1798                 :          0 :                         info[idx].offset = off_be;
    1799                 :            :                 break;
    1800                 :            :         case RTE_FLOW_FIELD_IPV6_DSCP:
    1801                 :            :                 MLX5_ASSERT(data->offset + width <= 6);
    1802                 :            :                 /*
    1803                 :            :                  * IPv6 DSCP uses OUT_IPV6_TRAFFIC_CLASS as ID but it starts from 2
    1804                 :            :                  * bits left. Shift the mask left for IPv6 DSCP. Do it here because
    1805                 :            :                  * it's needed to distinguish DSCP from ECN in data field construct
    1806                 :            :                  */
    1807         [ #  # ]:          0 :                 if (mlx5_dv_modify_ipv6_traffic_class_supported(priv)) {
    1808                 :          0 :                         off_be = 6 - (data->offset + width) + MLX5_IPV6_HDR_DSCP_SHIFT;
    1809                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    1810                 :            :                                                 MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS};
    1811                 :            :                 } else {
    1812                 :          0 :                         off_be = 6 - (data->offset + width);
    1813                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    1814                 :            :                                                 MLX5_MODI_OUT_IP_DSCP};
    1815                 :            :                 }
    1816         [ #  # ]:          0 :                 if (mask)
    1817                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1818                 :            :                 else
    1819                 :          0 :                         info[idx].offset = off_be;
    1820                 :            :                 break;
    1821                 :          0 :         case RTE_FLOW_FIELD_IPV6_TRAFFIC_CLASS:
    1822                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1823                 :          0 :                 off_be = 8 - (data->offset + width);
    1824         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_TRAFFIC_CLASS, data->level);
    1825                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1826         [ #  # ]:          0 :                 if (mask)
    1827                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1828                 :            :                 else
    1829                 :          0 :                         info[idx].offset = off_be;
    1830                 :            :                 break;
    1831                 :          0 :         case RTE_FLOW_FIELD_IPV6_FLOW_LABEL:
    1832                 :            :                 MLX5_ASSERT(data->offset + width <= 20);
    1833                 :          0 :                 off_be = 20 - (data->offset + width);
    1834         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_FLOW_LABEL, data->level);
    1835                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1836         [ #  # ]:          0 :                 if (mask)
    1837                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1838                 :            :                 else
    1839                 :          0 :                         info[idx].offset = off_be;
    1840                 :            :                 break;
    1841                 :          0 :         case RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN:
    1842                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1843                 :          0 :                 off_be = 16 - (data->offset + width);
    1844         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_PAYLOAD_LEN, data->level);
    1845                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1846         [ #  # ]:          0 :                 if (mask)
    1847                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1848                 :            :                 else
    1849                 :          0 :                         info[idx].offset = off_be;
    1850                 :            :                 break;
    1851                 :          0 :         case RTE_FLOW_FIELD_IPV6_HOPLIMIT:
    1852                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1853                 :          0 :                 off_be = 8 - (data->offset + width);
    1854         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_HOPLIMIT, data->level);
    1855                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1856         [ #  # ]:          0 :                 if (mask)
    1857                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1858                 :            :                 else
    1859                 :          0 :                         info[idx].offset = off_be;
    1860                 :            :                 break;
    1861                 :          0 :         case RTE_FLOW_FIELD_IPV6_SRC: {
    1862                 :            :                 /*
    1863                 :            :                  * Fields corresponding to IPv6 source address bytes
    1864                 :            :                  * arranged according to network byte ordering.
    1865                 :            :                  */
    1866                 :          0 :                 struct field_modify_info fields[] = {
    1867         [ #  # ]:          0 :                         { 4, 0, CALC_MODI_ID(SIPV6_127_96, data->level)},
    1868         [ #  # ]:          0 :                         { 4, 4, CALC_MODI_ID(SIPV6_95_64, data->level)},
    1869         [ #  # ]:          0 :                         { 4, 8, CALC_MODI_ID(SIPV6_63_32, data->level)},
    1870         [ #  # ]:          0 :                         { 4, 12, CALC_MODI_ID(SIPV6_31_0, data->level)},
    1871                 :            :                 };
    1872                 :            :                 /* First mask to be modified is the mask of 4th address byte. */
    1873                 :            :                 uint32_t midx = 3;
    1874                 :            : 
    1875                 :            :                 MLX5_ASSERT(data->offset + width <= 128);
    1876                 :          0 :                 off_be = 128 - (data->offset + width);
    1877         [ #  # ]:          0 :                 while (width > 0 && midx > 0) {
    1878         [ #  # ]:          0 :                         if (off_be < 32) {
    1879                 :          0 :                                 info[idx] = fields[midx];
    1880                 :          0 :                                 length = off_be + width <= 32 ?
    1881         [ #  # ]:          0 :                                          width : 32 - off_be;
    1882         [ #  # ]:          0 :                                 if (mask)
    1883         [ #  # ]:          0 :                                         mask[midx] = flow_modify_info_mask_32
    1884                 :            :                                                 (length, off_be);
    1885                 :            :                                 else
    1886                 :          0 :                                         info[idx].offset = off_be;
    1887                 :          0 :                                 width -= length;
    1888                 :            :                                 off_be = 0;
    1889                 :          0 :                                 idx++;
    1890                 :            :                         } else {
    1891                 :          0 :                                 off_be -= 32;
    1892                 :            :                         }
    1893                 :          0 :                         midx--;
    1894                 :            :                 }
    1895         [ #  # ]:          0 :                 if (!width)
    1896                 :            :                         break;
    1897                 :          0 :                 info[idx] = fields[midx];
    1898         [ #  # ]:          0 :                 if (mask)
    1899         [ #  # ]:          0 :                         mask[midx] = flow_modify_info_mask_32(width, off_be);
    1900                 :            :                 else
    1901                 :          0 :                         info[idx].offset = off_be;
    1902                 :            :                 break;
    1903                 :            :         }
    1904                 :          0 :         case RTE_FLOW_FIELD_IPV6_DST: {
    1905                 :            :                 /*
    1906                 :            :                  * Fields corresponding to IPv6 destination address bytes
    1907                 :            :                  * arranged according to network byte ordering.
    1908                 :            :                  */
    1909                 :          0 :                 struct field_modify_info fields[] = {
    1910         [ #  # ]:          0 :                         { 4, 0, CALC_MODI_ID(DIPV6_127_96, data->level)},
    1911         [ #  # ]:          0 :                         { 4, 4, CALC_MODI_ID(DIPV6_95_64, data->level)},
    1912         [ #  # ]:          0 :                         { 4, 8, CALC_MODI_ID(DIPV6_63_32, data->level)},
    1913         [ #  # ]:          0 :                         { 4, 12, CALC_MODI_ID(DIPV6_31_0, data->level)},
    1914                 :            :                 };
    1915                 :            :                 /* First mask to be modified is the mask of 4th address byte. */
    1916                 :            :                 uint32_t midx = 3;
    1917                 :            : 
    1918                 :            :                 MLX5_ASSERT(data->offset + width <= 128);
    1919                 :          0 :                 off_be = 128 - (data->offset + width);
    1920         [ #  # ]:          0 :                 while (width > 0 && midx > 0) {
    1921         [ #  # ]:          0 :                         if (off_be < 32) {
    1922                 :          0 :                                 info[idx] = fields[midx];
    1923                 :          0 :                                 length = off_be + width <= 32 ?
    1924         [ #  # ]:          0 :                                          width : 32 - off_be;
    1925         [ #  # ]:          0 :                                 if (mask)
    1926         [ #  # ]:          0 :                                         mask[midx] = flow_modify_info_mask_32
    1927                 :            :                                                 (length, off_be);
    1928                 :            :                                 else
    1929                 :          0 :                                         info[idx].offset = off_be;
    1930                 :          0 :                                 width -= length;
    1931                 :            :                                 off_be = 0;
    1932                 :          0 :                                 idx++;
    1933                 :            :                         } else {
    1934                 :          0 :                                 off_be -= 32;
    1935                 :            :                         }
    1936                 :          0 :                         midx--;
    1937                 :            :                 }
    1938         [ #  # ]:          0 :                 if (!width)
    1939                 :            :                         break;
    1940                 :          0 :                 info[idx] = fields[midx];
    1941         [ #  # ]:          0 :                 if (mask)
    1942         [ #  # ]:          0 :                         mask[midx] = flow_modify_info_mask_32(width, off_be);
    1943                 :            :                 else
    1944                 :          0 :                         info[idx].offset = off_be;
    1945                 :            :                 break;
    1946                 :            :         }
    1947                 :          0 :         case RTE_FLOW_FIELD_TCP_PORT_SRC:
    1948                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1949                 :          0 :                 off_be = 16 - (data->offset + width);
    1950         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_SPORT, data->level);
    1951                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1952         [ #  # ]:          0 :                 if (mask)
    1953                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1954                 :            :                 else
    1955                 :          0 :                         info[idx].offset = off_be;
    1956                 :            :                 break;
    1957                 :          0 :         case RTE_FLOW_FIELD_TCP_PORT_DST:
    1958                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1959                 :          0 :                 off_be = 16 - (data->offset + width);
    1960         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_DPORT, data->level);
    1961                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1962         [ #  # ]:          0 :                 if (mask)
    1963                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1964                 :            :                 else
    1965                 :          0 :                         info[idx].offset = off_be;
    1966                 :            :                 break;
    1967                 :          0 :         case RTE_FLOW_FIELD_TCP_SEQ_NUM:
    1968                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1969                 :          0 :                 off_be = 32 - (data->offset + width);
    1970         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_SEQ_NUM, data->level);
    1971                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1972         [ #  # ]:          0 :                 if (mask)
    1973                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1974                 :            :                 else
    1975                 :          0 :                         info[idx].offset = off_be;
    1976                 :            :                 break;
    1977                 :          0 :         case RTE_FLOW_FIELD_TCP_ACK_NUM:
    1978                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1979                 :          0 :                 off_be = 32 - (data->offset + width);
    1980         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_ACK_NUM, data->level);
    1981                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1982         [ #  # ]:          0 :                 if (mask)
    1983                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1984                 :            :                 else
    1985                 :          0 :                         info[idx].offset = off_be;
    1986                 :            :                 break;
    1987                 :          0 :         case RTE_FLOW_FIELD_TCP_FLAGS:
    1988                 :            :                 MLX5_ASSERT(data->offset + width <= 9);
    1989                 :          0 :                 off_be = 9 - (data->offset + width);
    1990         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_FLAGS, data->level);
    1991                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1992         [ #  # ]:          0 :                 if (mask)
    1993                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1994                 :            :                 else
    1995                 :          0 :                         info[idx].offset = off_be;
    1996                 :            :                 break;
    1997                 :          0 :         case RTE_FLOW_FIELD_TCP_DATA_OFFSET:
    1998                 :            :                 MLX5_ASSERT(data->offset + width <= 4);
    1999                 :          0 :                 off_be = 4 - (data->offset + width);
    2000         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_DATA_OFFSET, data->level);
    2001                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    2002         [ #  # ]:          0 :                 if (mask)
    2003                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2004                 :            :                 else
    2005                 :          0 :                         info[idx].offset = off_be;
    2006                 :            :                 break;
    2007                 :          0 :         case RTE_FLOW_FIELD_UDP_PORT_SRC:
    2008                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2009                 :          0 :                 off_be = 16 - (data->offset + width);
    2010         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(UDP_SPORT, data->level);
    2011                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    2012         [ #  # ]:          0 :                 if (mask)
    2013                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    2014                 :            :                 else
    2015                 :          0 :                         info[idx].offset = off_be;
    2016                 :            :                 break;
    2017                 :          0 :         case RTE_FLOW_FIELD_UDP_PORT_DST:
    2018                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2019                 :          0 :                 off_be = 16 - (data->offset + width);
    2020         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(UDP_DPORT, data->level);
    2021                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    2022         [ #  # ]:          0 :                 if (mask)
    2023                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    2024                 :            :                 else
    2025                 :          0 :                         info[idx].offset = off_be;
    2026                 :            :                 break;
    2027                 :          0 :         case RTE_FLOW_FIELD_VXLAN_VNI:
    2028                 :            :         case RTE_FLOW_FIELD_GENEVE_VNI:
    2029                 :            :                 MLX5_ASSERT(data->offset + width <= 24);
    2030                 :            :                 /* VNI is on bits 31-8 of TUNNEL_HDR_DW_1. */
    2031                 :          0 :                 off_be = 24 - (data->offset + width) + 8;
    2032                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2033                 :            :                                         MLX5_MODI_TUNNEL_HDR_DW_1};
    2034         [ #  # ]:          0 :                 if (mask)
    2035                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2036                 :            :                 else
    2037                 :          0 :                         info[idx].offset = off_be;
    2038                 :            :                 break;
    2039                 :          0 :         case RTE_FLOW_FIELD_VXLAN_LAST_RSVD:
    2040                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2041                 :            :                 /* Last_rsvd is on bits 7-0 of TUNNEL_HDR_DW_1. */
    2042                 :          0 :                 off_be = 8 - (data->offset + width);
    2043                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, MLX5_MODI_TUNNEL_HDR_DW_1};
    2044         [ #  # ]:          0 :                 if (mask)
    2045                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2046                 :            :                 else
    2047                 :          0 :                         info[idx].offset = off_be;
    2048                 :            :                 break;
    2049                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_TYPE:
    2050                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2051                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2052         [ #  # ]:          0 :                 if (modi_id < 0)
    2053                 :            :                         return;
    2054                 :            :                 /* Type is on bits 16-8 of GENEVE option header (DW0). */
    2055                 :          0 :                 off_be = 32 - (16 + data->offset + width);
    2056                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2057         [ #  # ]:          0 :                 if (mask)
    2058                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2059                 :            :                 else
    2060                 :          0 :                         info[idx].offset = off_be;
    2061                 :            :                 break;
    2062                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_CLASS:
    2063                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2064                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2065         [ #  # ]:          0 :                 if (modi_id < 0)
    2066                 :            :                         return;
    2067                 :            :                 /* Class is on bits 31-16 of GENEVE option header (DW0). */
    2068                 :          0 :                 off_be = 32 - (data->offset + width);
    2069                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2070         [ #  # ]:          0 :                 if (mask)
    2071                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2072                 :            :                 else
    2073                 :          0 :                         info[idx].offset = off_be;
    2074                 :            :                 break;
    2075                 :          0 :         case RTE_FLOW_FIELD_GENEVE_OPT_DATA:
    2076         [ #  # ]:          0 :                 if ((data->offset % 32) + width > 32) {
    2077                 :          0 :                         DRV_LOG(ERR, "Geneve TLV option data is per DW.");
    2078                 :          0 :                         return;
    2079                 :            :                 }
    2080                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2081         [ #  # ]:          0 :                 if (modi_id < 0)
    2082                 :            :                         return;
    2083                 :            :                 /* Use offset inside DW. */
    2084                 :          0 :                 off_be = 32 - ((data->offset % 32) + width);
    2085                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2086         [ #  # ]:          0 :                 if (mask)
    2087                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2088                 :            :                 else
    2089                 :          0 :                         info[idx].offset = off_be;
    2090                 :            :                 break;
    2091                 :          0 :         case RTE_FLOW_FIELD_GTP_TEID:
    2092                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2093                 :          0 :                 off_be = 32 - (data->offset + width);
    2094                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2095                 :            :                                         MLX5_MODI_GTP_TEID};
    2096         [ #  # ]:          0 :                 if (mask)
    2097                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2098                 :            :                 else
    2099                 :          0 :                         info[idx].offset = off_be;
    2100                 :            :                 break;
    2101                 :          0 :         case RTE_FLOW_FIELD_MPLS:
    2102                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2103                 :          0 :                 off_be = 32 - (data->offset + width);
    2104                 :            :                 modi_id = mlx5_mpls_modi_field_get(data);
    2105                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2106         [ #  # ]:          0 :                 if (mask)
    2107                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2108                 :            :                 else
    2109                 :          0 :                         info[idx].offset = off_be;
    2110                 :            :                 break;
    2111                 :            :         case RTE_FLOW_FIELD_TAG:
    2112                 :            :                 {
    2113                 :            :                         MLX5_ASSERT(data->offset + width <= 32);
    2114                 :            :                         uint8_t tag_index = flow_tag_index_get(data);
    2115                 :            :                         int reg;
    2116                 :            : 
    2117                 :            :                         off_be = (tag_index == RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX) ?
    2118         [ #  # ]:          0 :                                  16 - (data->offset + width) + 16 : data->offset;
    2119         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    2120         [ #  # ]:          0 :                                 reg = flow_hw_get_reg_id(dev,
    2121                 :            :                                                          RTE_FLOW_ITEM_TYPE_TAG,
    2122                 :            :                                                          tag_index);
    2123                 :            :                         else
    2124                 :          0 :                                 reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG,
    2125                 :            :                                                            tag_index, error);
    2126         [ #  # ]:          0 :                         if (reg < 0)
    2127                 :            :                                 return;
    2128                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2129                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
    2130                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2131                 :          0 :                                                 reg_to_field[reg]};
    2132         [ #  # ]:          0 :                         if (mask)
    2133                 :          0 :                                 mask[idx] = flow_modify_info_mask_32
    2134                 :            :                                         (width, off_be);
    2135                 :            :                         else
    2136                 :          0 :                                 info[idx].offset = off_be;
    2137                 :            :                 }
    2138                 :            :                 break;
    2139                 :          0 :         case RTE_FLOW_FIELD_MARK:
    2140                 :            :                 {
    2141                 :          0 :                         uint32_t mark_mask = priv->sh->dv_mark_mask;
    2142                 :            :                         uint32_t mark_count = rte_popcount32(mark_mask);
    2143                 :            :                         RTE_SET_USED(mark_count);
    2144                 :            :                         MLX5_ASSERT(data->offset + width <= mark_count);
    2145                 :          0 :                         int reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK,
    2146                 :            :                                                        0, error);
    2147         [ #  # ]:          0 :                         if (reg < 0)
    2148                 :            :                                 return;
    2149                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2150                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
    2151                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2152                 :          0 :                                                 reg_to_field[reg]};
    2153         [ #  # ]:          0 :                         if (mask)
    2154                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2155         [ #  # ]:          0 :                                         (width, data->offset, mark_mask);
    2156                 :            :                         else
    2157                 :          0 :                                 info[idx].offset = data->offset;
    2158                 :            :                 }
    2159                 :            :                 break;
    2160                 :          0 :         case RTE_FLOW_FIELD_META:
    2161                 :            :                 {
    2162                 :          0 :                         uint32_t meta_mask = priv->sh->dv_meta_mask;
    2163                 :            :                         uint32_t meta_count = rte_popcount32(meta_mask);
    2164                 :            :                         RTE_SET_USED(meta_count);
    2165                 :            :                         MLX5_ASSERT(data->offset + width <= meta_count);
    2166                 :          0 :                         int reg = flow_dv_get_metadata_reg(dev, attr, error);
    2167         [ #  # ]:          0 :                         if (reg < 0)
    2168                 :            :                                 return;
    2169                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2170                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
    2171                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2172                 :          0 :                                                 reg_to_field[reg]};
    2173         [ #  # ]:          0 :                         if (mask)
    2174                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2175         [ #  # ]:          0 :                                         (width, data->offset, meta_mask);
    2176                 :            :                         else
    2177                 :          0 :                                 info[idx].offset = data->offset;
    2178                 :            :                 }
    2179                 :            :                 break;
    2180                 :          0 :         case RTE_FLOW_FIELD_IPV4_ECN:
    2181                 :            :                 MLX5_ASSERT(data->offset + width <= 2);
    2182                 :          0 :                 off_be = 2 - (data->offset + width);
    2183         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IP_ECN, data->level);
    2184                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    2185         [ #  # ]:          0 :                 if (mask)
    2186                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2187                 :            :                 else
    2188                 :          0 :                         info[idx].offset = off_be;
    2189                 :            :                 break;
    2190                 :          0 :         case RTE_FLOW_FIELD_IPV6_ECN:
    2191                 :            :                 MLX5_ASSERT(data->offset + width <= 2);
    2192                 :          0 :                 off_be = 2 - (data->offset + width);
    2193         [ #  # ]:          0 :                 if (mlx5_dv_modify_ipv6_traffic_class_supported(priv))
    2194                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    2195                 :            :                                                 MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS};
    2196                 :            :                 else
    2197                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    2198                 :            :                                                 MLX5_MODI_OUT_IP_ECN};
    2199         [ #  # ]:          0 :                 if (mask)
    2200                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2201                 :            :                 else
    2202                 :          0 :                         info[idx].offset = off_be;
    2203                 :            :                 break;
    2204                 :          0 :         case RTE_FLOW_FIELD_GTP_PSC_QFI:
    2205                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2206                 :          0 :                 off_be = data->offset + 8;
    2207                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2208                 :            :                                         MLX5_MODI_GTPU_FIRST_EXT_DW_0};
    2209         [ #  # ]:          0 :                 if (mask)
    2210                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2211                 :            :                 else
    2212                 :          0 :                         info[idx].offset = off_be;
    2213                 :            :                 break;
    2214                 :          0 :         case MLX5_RTE_FLOW_FIELD_META_REG:
    2215                 :            :                 {
    2216         [ #  # ]:          0 :                         uint32_t meta_mask = priv->sh->dv_meta_mask;
    2217                 :            :                         uint32_t meta_count = rte_popcount32(meta_mask);
    2218                 :            :                         uint8_t reg = flow_tag_index_get(data);
    2219                 :            : 
    2220                 :            :                         RTE_SET_USED(meta_count);
    2221                 :            :                         MLX5_ASSERT(data->offset + width <= meta_count);
    2222                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2223                 :            :                         MLX5_ASSERT(reg < RTE_DIM(reg_to_field));
    2224                 :          0 :                         info[idx] = (struct field_modify_info){4, 0, reg_to_field[reg]};
    2225         [ #  # ]:          0 :                         if (mask)
    2226                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2227         [ #  # ]:          0 :                                         (width, data->offset, meta_mask);
    2228                 :            :                         else
    2229                 :          0 :                                 info[idx].offset = data->offset;
    2230                 :            :                 }
    2231                 :            :                 break;
    2232                 :          0 :         case RTE_FLOW_FIELD_METER_COLOR:
    2233                 :            :                 {
    2234                 :            :                         const uint32_t color_mask =
    2235                 :            :                                 (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
    2236                 :            :                         int reg;
    2237                 :            : 
    2238         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    2239                 :            :                                 reg = flow_hw_get_reg_id
    2240                 :            :                                         (dev,
    2241                 :            :                                          RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
    2242                 :            :                         else
    2243                 :          0 :                                 reg = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
    2244                 :            :                                                        0, error);
    2245         [ #  # ]:          0 :                         if (reg < 0)
    2246                 :            :                                 return;
    2247                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2248                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field));
    2249                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2250                 :          0 :                                                 reg_to_field[reg]};
    2251         [ #  # ]:          0 :                         if (mask)
    2252                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2253         [ #  # ]:          0 :                                         (width, data->offset, color_mask);
    2254                 :            :                         else
    2255                 :          0 :                                 info[idx].offset = data->offset;
    2256                 :            :                 }
    2257                 :            :                 break;
    2258                 :          0 :         case RTE_FLOW_FIELD_IPV4_PROTO: /* Fall-through. */
    2259                 :            :         case RTE_FLOW_FIELD_IPV6_PROTO:
    2260                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2261                 :          0 :                 off_be = 8 - (data->offset + width);
    2262                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, MLX5_MODI_OUT_IP_PROTOCOL};
    2263         [ #  # ]:          0 :                 if (mask)
    2264                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2265                 :            :                 else
    2266                 :          0 :                         info[idx].offset = off_be;
    2267                 :            :                 break;
    2268                 :          0 :         case RTE_FLOW_FIELD_ESP_PROTO:
    2269                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2270                 :          0 :                 off_be = 8 - (data->offset + width);
    2271                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, MLX5_MODI_OUT_IPSEC_NEXT_HDR};
    2272         [ #  # ]:          0 :                 if (mask)
    2273                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2274                 :            :                 else
    2275                 :          0 :                         info[idx].offset = off_be;
    2276                 :            :                 break;
    2277                 :          0 :         case RTE_FLOW_FIELD_ESP_SPI:
    2278                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2279                 :          0 :                 off_be = 32 - (data->offset + width);
    2280         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(ESP_SPI, data->level);
    2281                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2282         [ #  # ]:          0 :                 if (mask)
    2283                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2284                 :            :                 else
    2285                 :          0 :                         info[idx].offset = off_be;
    2286                 :            :                 break;
    2287                 :          0 :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    2288                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2289                 :          0 :                 off_be = 32 - (data->offset + width);
    2290         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(ESP_SEQ_NUM, data->level);
    2291                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2292         [ #  # ]:          0 :                 if (mask)
    2293                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2294                 :            :                 else
    2295                 :          0 :                         info[idx].offset = off_be;
    2296                 :            :                 break;
    2297                 :          0 :         case RTE_FLOW_FIELD_FLEX_ITEM:
    2298                 :            :                 MLX5_ASSERT(data->flex_handle != NULL && !(data->offset & 0x7));
    2299                 :          0 :                 mlx5_modify_flex_item(dev, (const struct mlx5_flex_item *)data->flex_handle,
    2300                 :            :                                       data, info, mask, width);
    2301                 :          0 :                 break;
    2302                 :          0 :         case RTE_FLOW_FIELD_HASH_RESULT:
    2303                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2304                 :          0 :                 off_be = 32 - (data->offset + width);
    2305                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2306                 :            :                                                        MLX5_MODI_HASH_RESULT};
    2307         [ #  # ]:          0 :                 if (mask)
    2308                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2309                 :            :                 else
    2310                 :          0 :                         info[idx].offset = off_be;
    2311                 :            :                 break;
    2312                 :            :         case RTE_FLOW_FIELD_POINTER:
    2313                 :            :         case RTE_FLOW_FIELD_VALUE:
    2314                 :            :         default:
    2315                 :            :                 MLX5_ASSERT(false);
    2316                 :            :                 break;
    2317                 :            :         }
    2318                 :            : }
    2319                 :            : 
    2320                 :            : /**
    2321                 :            :  * Convert modify_field action to DV specification.
    2322                 :            :  *
    2323                 :            :  * @param[in] dev
    2324                 :            :  *   Pointer to the rte_eth_dev structure.
    2325                 :            :  * @param[in,out] resource
    2326                 :            :  *   Pointer to the modify-header resource.
    2327                 :            :  * @param[in] action
    2328                 :            :  *   Pointer to action specification.
    2329                 :            :  * @param[in] attr
    2330                 :            :  *   Attributes of flow that includes this item.
    2331                 :            :  * @param[out] error
    2332                 :            :  *   Pointer to the error structure.
    2333                 :            :  *
    2334                 :            :  * @return
    2335                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2336                 :            :  */
    2337                 :            : static int
    2338                 :          0 : flow_dv_convert_action_modify_field
    2339                 :            :                         (struct rte_eth_dev *dev,
    2340                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    2341                 :            :                          const struct rte_flow_action *action,
    2342                 :            :                          const struct rte_flow_attr *attr,
    2343                 :            :                          struct rte_flow_error *error)
    2344                 :            : {
    2345                 :          0 :         const struct rte_flow_action_modify_field *conf =
    2346                 :            :                 (const struct rte_flow_action_modify_field *)(action->conf);
    2347                 :          0 :         struct rte_flow_item item = {
    2348                 :            :                 .spec = NULL,
    2349                 :            :                 .mask = NULL
    2350                 :            :         };
    2351                 :          0 :         struct field_modify_info field[MLX5_ACT_MAX_MOD_FIELDS] = {
    2352                 :            :                                                                 {0, 0, 0} };
    2353                 :          0 :         struct field_modify_info dcopy[MLX5_ACT_MAX_MOD_FIELDS] = {
    2354                 :            :                                                                 {0, 0, 0} };
    2355                 :          0 :         uint32_t mask[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0};
    2356                 :          0 :         uint32_t type, meta = 0, dscp = 0;
    2357                 :            : 
    2358         [ #  # ]:          0 :         if (conf->src.field == RTE_FLOW_FIELD_POINTER ||
    2359                 :            :             conf->src.field == RTE_FLOW_FIELD_VALUE) {
    2360                 :          0 :                 type = conf->operation == RTE_FLOW_MODIFY_SET ?
    2361         [ #  # ]:          0 :                         MLX5_MODIFICATION_TYPE_SET : MLX5_MODIFICATION_TYPE_ADD;
    2362                 :            :                 /** For SET fill the destination field (field) first. */
    2363                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->dst, field, mask,
    2364                 :          0 :                                                   conf->width, dev,
    2365                 :            :                                                   attr, error);
    2366                 :          0 :                 item.spec = conf->src.field == RTE_FLOW_FIELD_POINTER ?
    2367         [ #  # ]:          0 :                                         (void *)(uintptr_t)conf->src.pvalue :
    2368                 :            :                                         (void *)(uintptr_t)&conf->src.value;
    2369         [ #  # ]:          0 :                 if (conf->dst.field == RTE_FLOW_FIELD_META ||
    2370         [ #  # ]:          0 :                     conf->dst.field == RTE_FLOW_FIELD_TAG ||
    2371                 :            :                     conf->dst.field == RTE_FLOW_FIELD_METER_COLOR) {
    2372                 :          0 :                         meta = *(const unaligned_uint32_t *)item.spec;
    2373         [ #  # ]:          0 :                         meta = rte_cpu_to_be_32(meta);
    2374                 :          0 :                         item.spec = &meta;
    2375                 :            :                 }
    2376   [ #  #  #  # ]:          0 :                 if (mlx5_dv_modify_ipv6_traffic_class_supported(dev->data->dev_private) &&
    2377                 :          0 :                     conf->dst.field == RTE_FLOW_FIELD_IPV6_DSCP &&
    2378         [ #  # ]:          0 :                     !(mask[0] & MLX5_IPV6_HDR_ECN_MASK)) {
    2379                 :          0 :                         dscp = *(const unaligned_uint32_t *)item.spec;
    2380                 :            :                         /*
    2381                 :            :                          * IPv6 DSCP uses OUT_IPV6_TRAFFIC_CLASS as ID but it starts from 2
    2382                 :            :                          * bits left. Shift the data left for IPv6 DSCP
    2383                 :            :                          */
    2384                 :          0 :                         dscp <<= MLX5_IPV6_HDR_DSCP_SHIFT;
    2385                 :          0 :                         item.spec = &dscp;
    2386                 :            :                 }
    2387                 :            :         } else {
    2388                 :            :                 type = MLX5_MODIFICATION_TYPE_COPY;
    2389                 :            :                 /** For COPY fill the destination field (dcopy) without mask. */
    2390                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->dst, dcopy, NULL,
    2391                 :          0 :                                                   conf->width, dev,
    2392                 :            :                                                   attr, error);
    2393                 :            :                 /** Then construct the source field (field) with mask. */
    2394                 :          0 :                 mlx5_flow_field_id_to_modify_info(&conf->src, field, mask,
    2395                 :          0 :                                                   conf->width, dev,
    2396                 :            :                                                   attr, error);
    2397                 :            :         }
    2398                 :          0 :         item.mask = &mask;
    2399                 :          0 :         return flow_dv_convert_modify_action(&item,
    2400                 :            :                         field, dcopy, resource, type, error);
    2401                 :            : }
    2402                 :            : 
    2403                 :            : /**
    2404                 :            :  * Validate MARK item.
    2405                 :            :  *
    2406                 :            :  * @param[in] dev
    2407                 :            :  *   Pointer to the rte_eth_dev structure.
    2408                 :            :  * @param[in] item
    2409                 :            :  *   Item specification.
    2410                 :            :  * @param[in] attr
    2411                 :            :  *   Attributes of flow that includes this item.
    2412                 :            :  * @param[out] error
    2413                 :            :  *   Pointer to error structure.
    2414                 :            :  *
    2415                 :            :  * @return
    2416                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2417                 :            :  */
    2418                 :            : static int
    2419                 :          0 : flow_dv_validate_item_mark(struct rte_eth_dev *dev,
    2420                 :            :                            const struct rte_flow_item *item,
    2421                 :            :                            const struct rte_flow_attr *attr __rte_unused,
    2422                 :            :                            struct rte_flow_error *error)
    2423                 :            : {
    2424                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2425                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    2426                 :          0 :         const struct rte_flow_item_mark *spec = item->spec;
    2427                 :          0 :         const struct rte_flow_item_mark *mask = item->mask;
    2428                 :          0 :         const struct rte_flow_item_mark nic_mask = {
    2429                 :          0 :                 .id = priv->sh->dv_mark_mask,
    2430                 :            :         };
    2431                 :            :         int ret;
    2432                 :            : 
    2433         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
    2434                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2435                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2436                 :            :                                           "extended metadata feature"
    2437                 :            :                                           " isn't enabled");
    2438         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    2439                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2440                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2441                 :            :                                           "extended metadata register"
    2442                 :            :                                           " isn't supported");
    2443         [ #  # ]:          0 :         if (!nic_mask.id)
    2444                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2445                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2446                 :            :                                           "extended metadata register"
    2447                 :            :                                           " isn't available");
    2448                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    2449         [ #  # ]:          0 :         if (ret < 0)
    2450                 :            :                 return ret;
    2451         [ #  # ]:          0 :         if (!spec)
    2452                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2453                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2454                 :          0 :                                           item->spec,
    2455                 :            :                                           "data cannot be empty");
    2456         [ #  # ]:          0 :         if (spec->id >= (MLX5_FLOW_MARK_MAX & nic_mask.id))
    2457                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2458                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    2459                 :          0 :                                           &spec->id,
    2460                 :            :                                           "mark id exceeds the limit");
    2461         [ #  # ]:          0 :         if (!mask)
    2462                 :            :                 mask = &nic_mask;
    2463         [ #  # ]:          0 :         if (!mask->id)
    2464                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2465                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    2466                 :            :                                         "mask cannot be zero");
    2467                 :            : 
    2468                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2469                 :            :                                         (const uint8_t *)&nic_mask,
    2470                 :            :                                         sizeof(struct rte_flow_item_mark),
    2471                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2472                 :            :         if (ret < 0)
    2473                 :            :                 return ret;
    2474                 :            :         return 0;
    2475                 :            : }
    2476                 :            : 
    2477                 :            : /**
    2478                 :            :  * Validate META item.
    2479                 :            :  *
    2480                 :            :  * @param[in] dev
    2481                 :            :  *   Pointer to the rte_eth_dev structure.
    2482                 :            :  * @param[in] item
    2483                 :            :  *   Item specification.
    2484                 :            :  * @param[in] attr
    2485                 :            :  *   Attributes of flow that includes this item.
    2486                 :            :  * @param[out] error
    2487                 :            :  *   Pointer to error structure.
    2488                 :            :  *
    2489                 :            :  * @return
    2490                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2491                 :            :  */
    2492                 :            : static int
    2493                 :          0 : flow_dv_validate_item_meta(struct rte_eth_dev *dev __rte_unused,
    2494                 :            :                            const struct rte_flow_item *item,
    2495                 :            :                            const struct rte_flow_attr *attr,
    2496                 :            :                            struct rte_flow_error *error)
    2497                 :            : {
    2498                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2499                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    2500                 :          0 :         const struct rte_flow_item_meta *spec = item->spec;
    2501                 :          0 :         const struct rte_flow_item_meta *mask = item->mask;
    2502                 :          0 :         struct rte_flow_item_meta nic_mask = {
    2503                 :            :                 .data = UINT32_MAX
    2504                 :            :         };
    2505                 :            :         int reg;
    2506                 :            :         int ret;
    2507                 :            : 
    2508         [ #  # ]:          0 :         if (!spec)
    2509                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2510                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2511                 :            :                                           item->spec,
    2512                 :            :                                           "data cannot be empty");
    2513         [ #  # ]:          0 :         if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    2514         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev))
    2515                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2516                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2517                 :            :                                           "extended metadata register"
    2518                 :            :                                           " isn't supported");
    2519                 :          0 :                 reg = flow_dv_get_metadata_reg(dev, attr, error);
    2520         [ #  # ]:          0 :                 if (reg < 0)
    2521                 :            :                         return reg;
    2522         [ #  # ]:          0 :                 if (reg == REG_NON)
    2523                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2524                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2525                 :            :                                         "unavailable extended metadata register");
    2526         [ #  # ]:          0 :                 if (reg == REG_B)
    2527                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2528                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2529                 :            :                                           "match on reg_b "
    2530                 :            :                                           "isn't supported");
    2531         [ #  # ]:          0 :                 if (reg != REG_A)
    2532                 :          0 :                         nic_mask.data = priv->sh->dv_meta_mask;
    2533                 :            :         } else {
    2534         [ #  # ]:          0 :                 if (attr->transfer)
    2535                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2536                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2537                 :            :                                         "extended metadata feature "
    2538                 :            :                                         "should be enabled when "
    2539                 :            :                                         "meta item is requested "
    2540                 :            :                                         "with e-switch mode ");
    2541         [ #  # ]:          0 :                 if (attr->ingress)
    2542                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    2543                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2544                 :            :                                         "match on metadata for ingress "
    2545                 :            :                                         "is not supported in legacy "
    2546                 :            :                                         "metadata mode");
    2547                 :            :         }
    2548         [ #  # ]:          0 :         if (!mask)
    2549                 :            :                 mask = &rte_flow_item_meta_mask;
    2550         [ #  # ]:          0 :         if (!mask->data)
    2551                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2552                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    2553                 :            :                                         "mask cannot be zero");
    2554                 :            : 
    2555                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2556                 :            :                                         (const uint8_t *)&nic_mask,
    2557                 :            :                                         sizeof(struct rte_flow_item_meta),
    2558                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2559                 :          0 :         return ret;
    2560                 :            : }
    2561                 :            : 
    2562                 :            : /**
    2563                 :            :  * Validate TAG item.
    2564                 :            :  *
    2565                 :            :  * @param[in] dev
    2566                 :            :  *   Pointer to the rte_eth_dev structure.
    2567                 :            :  * @param[in] item
    2568                 :            :  *   Item specification.
    2569                 :            :  * @param[in] tag_bitmap
    2570                 :            :  *   Tag index bitmap.
    2571                 :            :  * @param[in] attr
    2572                 :            :  *   Attributes of flow that includes this item.
    2573                 :            :  * @param[out] error
    2574                 :            :  *   Pointer to error structure.
    2575                 :            :  *
    2576                 :            :  * @return
    2577                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2578                 :            :  */
    2579                 :            : static int
    2580                 :          0 : flow_dv_validate_item_tag(struct rte_eth_dev *dev,
    2581                 :            :                           const struct rte_flow_item *item,
    2582                 :            :                           uint32_t *tag_bitmap,
    2583                 :            :                           const struct rte_flow_attr *attr __rte_unused,
    2584                 :            :                           struct rte_flow_error *error)
    2585                 :            : {
    2586                 :          0 :         const struct rte_flow_item_tag *spec = item->spec;
    2587                 :          0 :         const struct rte_flow_item_tag *mask = item->mask;
    2588                 :          0 :         const struct rte_flow_item_tag nic_mask = {
    2589                 :            :                 .data = RTE_BE32(UINT32_MAX),
    2590                 :            :                 .index = 0xff,
    2591                 :            :         };
    2592                 :            :         int ret;
    2593                 :            : 
    2594         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    2595                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2596                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2597                 :            :                                           "extensive metadata register"
    2598                 :            :                                           " isn't supported");
    2599         [ #  # ]:          0 :         if (!spec)
    2600                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2601                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2602                 :          0 :                                           item->spec,
    2603                 :            :                                           "data cannot be empty");
    2604         [ #  # ]:          0 :         if (!mask)
    2605                 :            :                 mask = &rte_flow_item_tag_mask;
    2606         [ #  # ]:          0 :         if (!mask->data)
    2607                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2608                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    2609                 :            :                                         "mask cannot be zero");
    2610                 :            : 
    2611                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2612                 :            :                                         (const uint8_t *)&nic_mask,
    2613                 :            :                                         sizeof(struct rte_flow_item_tag),
    2614                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2615         [ #  # ]:          0 :         if (ret < 0)
    2616                 :            :                 return ret;
    2617         [ #  # ]:          0 :         if (mask->index != 0xff)
    2618                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2619                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    2620                 :            :                                           "partial mask for tag index"
    2621                 :            :                                           " is not supported");
    2622                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, spec->index, error);
    2623         [ #  # ]:          0 :         if (ret < 0)
    2624                 :            :                 return ret;
    2625                 :            :         MLX5_ASSERT(ret != REG_NON);
    2626         [ #  # ]:          0 :         if (*tag_bitmap & (1 << ret))
    2627                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2628                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    2629                 :          0 :                                           item->spec,
    2630                 :            :                                           "Duplicated tag index");
    2631                 :          0 :         *tag_bitmap |= 1 << ret;
    2632                 :          0 :         return 0;
    2633                 :            : }
    2634                 :            : 
    2635                 :            : /**
    2636                 :            :  * Validate vport item.
    2637                 :            :  *
    2638                 :            :  * @param[in] dev
    2639                 :            :  *   Pointer to the rte_eth_dev structure.
    2640                 :            :  * @param[in] item
    2641                 :            :  *   Item specification.
    2642                 :            :  * @param[in] attr
    2643                 :            :  *   Attributes of flow that includes this item.
    2644                 :            :  * @param[in] item_flags
    2645                 :            :  *   Bit-fields that holds the items detected until now.
    2646                 :            :  * @param[out] error
    2647                 :            :  *   Pointer to error structure.
    2648                 :            :  *
    2649                 :            :  * @return
    2650                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2651                 :            :  */
    2652                 :            : static int
    2653                 :          0 : flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
    2654                 :            :                               const struct rte_flow_item *item,
    2655                 :            :                               const struct rte_flow_attr *attr,
    2656                 :            :                               uint64_t item_flags,
    2657                 :            :                               struct mlx5_priv **act_priv,
    2658                 :            :                               struct rte_flow_error *error)
    2659                 :            : {
    2660                 :          0 :         const struct rte_flow_item_port_id *spec = item->spec;
    2661                 :          0 :         const struct rte_flow_item_port_id *mask = item->mask;
    2662                 :          0 :         const struct rte_flow_item_port_id switch_mask = {
    2663                 :            :                         .id = 0xffffffff,
    2664                 :            :         };
    2665                 :            :         struct mlx5_priv *esw_priv;
    2666                 :            :         struct mlx5_priv *dev_priv;
    2667                 :            :         int ret;
    2668                 :            : 
    2669         [ #  # ]:          0 :         if (!attr->transfer)
    2670                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2671                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    2672                 :            :                                           NULL,
    2673                 :            :                                           "match on port id is valid only"
    2674                 :            :                                           " when transfer flag is enabled");
    2675         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_ITEM_PORT_ID)
    2676                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2677                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2678                 :            :                                           "multiple source ports are not"
    2679                 :            :                                           " supported");
    2680         [ #  # ]:          0 :         if (!mask)
    2681                 :            :                 mask = &switch_mask;
    2682         [ #  # ]:          0 :         if (mask->id != 0xffffffff)
    2683                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2684                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM_MASK,
    2685                 :            :                                            mask,
    2686                 :            :                                            "no support for partial mask on"
    2687                 :            :                                            " \"id\" field");
    2688                 :          0 :         ret = mlx5_flow_item_acceptable
    2689                 :            :                                 (dev, item, (const uint8_t *)mask,
    2690                 :            :                                  (const uint8_t *)&rte_flow_item_port_id_mask,
    2691                 :            :                                  sizeof(struct rte_flow_item_port_id),
    2692                 :            :                                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2693         [ #  # ]:          0 :         if (ret)
    2694                 :            :                 return ret;
    2695         [ #  # ]:          0 :         if (!spec)
    2696                 :            :                 return 0;
    2697         [ #  # ]:          0 :         if (spec->id == MLX5_PORT_ESW_MGR)
    2698                 :            :                 return 0;
    2699                 :          0 :         esw_priv = mlx5_port_to_eswitch_info(spec->id, false);
    2700         [ #  # ]:          0 :         if (!esw_priv)
    2701                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2702                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
    2703                 :            :                                           "failed to obtain E-Switch info for"
    2704                 :            :                                           " port");
    2705                 :          0 :         dev_priv = mlx5_dev_to_eswitch_info(dev);
    2706         [ #  # ]:          0 :         if (!dev_priv)
    2707                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2708                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2709                 :            :                                           NULL,
    2710                 :            :                                           "failed to obtain E-Switch info");
    2711         [ #  # ]:          0 :         if (esw_priv->domain_id != dev_priv->domain_id)
    2712                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2713                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
    2714                 :            :                                           "cannot match on a port from a"
    2715                 :            :                                           " different E-Switch");
    2716                 :          0 :         *act_priv = esw_priv;
    2717                 :          0 :         return 0;
    2718                 :            : }
    2719                 :            : 
    2720                 :            : /**
    2721                 :            :  * Validate represented port item.
    2722                 :            :  *
    2723                 :            :  * @param[in] dev
    2724                 :            :  *   Pointer to the rte_eth_dev structure.
    2725                 :            :  * @param[in] item
    2726                 :            :  *   Item specification.
    2727                 :            :  * @param[in] attr
    2728                 :            :  *   Attributes of flow that includes this item.
    2729                 :            :  * @param[in] item_flags
    2730                 :            :  *   Bit-fields that holds the items detected until now.
    2731                 :            :  * @param[out] error
    2732                 :            :  *   Pointer to error structure.
    2733                 :            :  *
    2734                 :            :  * @return
    2735                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2736                 :            :  */
    2737                 :            : static int
    2738                 :          0 : flow_dv_validate_item_represented_port(struct rte_eth_dev *dev,
    2739                 :            :                                        const struct rte_flow_item *item,
    2740                 :            :                                        const struct rte_flow_attr *attr,
    2741                 :            :                                        uint64_t item_flags,
    2742                 :            :                                        struct mlx5_priv **act_priv,
    2743                 :            :                                        struct rte_flow_error *error)
    2744                 :            : {
    2745                 :          0 :         const struct rte_flow_item_ethdev *spec = item->spec;
    2746                 :          0 :         const struct rte_flow_item_ethdev *mask = item->mask;
    2747                 :          0 :         const struct rte_flow_item_ethdev switch_mask = {
    2748                 :            :                         .port_id = UINT16_MAX,
    2749                 :            :         };
    2750                 :            :         struct mlx5_priv *esw_priv;
    2751                 :            :         struct mlx5_priv *dev_priv;
    2752                 :            :         int ret;
    2753                 :            : 
    2754         [ #  # ]:          0 :         if (!attr->transfer)
    2755                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2756                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    2757                 :            :                                           "match on port id is valid only when transfer flag is enabled");
    2758         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT)
    2759                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2760                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2761                 :            :                                           "multiple source ports are not supported");
    2762         [ #  # ]:          0 :         if (!mask)
    2763                 :            :                 mask = &switch_mask;
    2764         [ #  # ]:          0 :         if (mask->port_id != UINT16_MAX)
    2765                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2766                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,
    2767                 :            :                                            "no support for partial mask on \"id\" field");
    2768                 :          0 :         ret = mlx5_flow_item_acceptable
    2769                 :            :                                 (dev, item, (const uint8_t *)mask,
    2770                 :            :                                  (const uint8_t *)&rte_flow_item_ethdev_mask,
    2771                 :            :                                  sizeof(struct rte_flow_item_ethdev),
    2772                 :            :                                  MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2773         [ #  # ]:          0 :         if (ret)
    2774                 :            :                 return ret;
    2775   [ #  #  #  # ]:          0 :         if (!spec || spec->port_id == UINT16_MAX)
    2776                 :            :                 return 0;
    2777                 :          0 :         esw_priv = mlx5_port_to_eswitch_info(spec->port_id, false);
    2778         [ #  # ]:          0 :         if (!esw_priv)
    2779                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2780                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
    2781                 :            :                                           "failed to obtain E-Switch info for port");
    2782                 :          0 :         dev_priv = mlx5_dev_to_eswitch_info(dev);
    2783         [ #  # ]:          0 :         if (!dev_priv)
    2784                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    2785                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2786                 :            :                                           NULL,
    2787                 :            :                                           "failed to obtain E-Switch info");
    2788         [ #  # ]:          0 :         if (esw_priv->domain_id != dev_priv->domain_id)
    2789                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2790                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
    2791                 :            :                                           "cannot match on a port from a different E-Switch");
    2792                 :          0 :         *act_priv = esw_priv;
    2793                 :          0 :         return 0;
    2794                 :            : }
    2795                 :            : 
    2796                 :            : /**
    2797                 :            :  * Validate VLAN item.
    2798                 :            :  *
    2799                 :            :  * @param[in] item
    2800                 :            :  *   Item specification.
    2801                 :            :  * @param[in] item_flags
    2802                 :            :  *   Bit-fields that holds the items detected until now.
    2803                 :            :  * @param[in] dev
    2804                 :            :  *   Ethernet device flow is being created on.
    2805                 :            :  * @param[out] error
    2806                 :            :  *   Pointer to error structure.
    2807                 :            :  *
    2808                 :            :  * @return
    2809                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2810                 :            :  */
    2811                 :            : int
    2812                 :          0 : mlx5_flow_dv_validate_item_vlan(const struct rte_flow_item *item,
    2813                 :            :                                 uint64_t item_flags,
    2814                 :            :                                 struct rte_eth_dev *dev,
    2815                 :            :                                 struct rte_flow_error *error)
    2816                 :            : {
    2817                 :          0 :         const struct rte_flow_item_vlan *mask = item->mask;
    2818                 :          0 :         const struct rte_flow_item_vlan nic_mask = {
    2819                 :            :                 .hdr.vlan_tci = RTE_BE16(UINT16_MAX),
    2820                 :            :                 .hdr.eth_proto = RTE_BE16(UINT16_MAX),
    2821                 :            :                 .has_more_vlan = 1,
    2822                 :            :         };
    2823                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    2824                 :            :         int ret;
    2825                 :            :         const uint64_t l34m = tunnel ? (MLX5_FLOW_LAYER_INNER_L3 |
    2826         [ #  # ]:          0 :                                         MLX5_FLOW_LAYER_INNER_L4) :
    2827                 :            :                                        (MLX5_FLOW_LAYER_OUTER_L3 |
    2828                 :            :                                         MLX5_FLOW_LAYER_OUTER_L4);
    2829         [ #  # ]:          0 :         const uint64_t vlanm = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
    2830                 :            :                                         MLX5_FLOW_LAYER_OUTER_VLAN;
    2831                 :            : 
    2832         [ #  # ]:          0 :         if (item_flags & vlanm)
    2833                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2834                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2835                 :            :                                           "multiple VLAN layers not supported");
    2836         [ #  # ]:          0 :         else if ((item_flags & l34m) != 0)
    2837                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2838                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2839                 :            :                                           "VLAN cannot follow L3/L4 layer");
    2840         [ #  # ]:          0 :         if (!mask)
    2841                 :            :                 mask = &rte_flow_item_vlan_mask;
    2842                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2843                 :            :                                         (const uint8_t *)&nic_mask,
    2844                 :            :                                         sizeof(struct rte_flow_item_vlan),
    2845                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2846         [ #  # ]:          0 :         if (ret)
    2847                 :            :                 return ret;
    2848   [ #  #  #  # ]:          0 :         if (!tunnel && mask->hdr.vlan_tci != RTE_BE16(0x0fff)) {
    2849                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    2850                 :            : 
    2851         [ #  # ]:          0 :                 if (priv->vmwa_context) {
    2852                 :            :                         /*
    2853                 :            :                          * Non-NULL context means we have a virtual machine
    2854                 :            :                          * and SR-IOV enabled, we have to create VLAN interface
    2855                 :            :                          * to make hypervisor to setup E-Switch vport
    2856                 :            :                          * context correctly. We avoid creating the multiple
    2857                 :            :                          * VLAN interfaces, so we cannot support VLAN tag mask.
    2858                 :            :                          */
    2859                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2860                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2861                 :            :                                                   item,
    2862                 :            :                                                   "VLAN tag mask is not"
    2863                 :            :                                                   " supported in virtual"
    2864                 :            :                                                   " environment");
    2865                 :            :                 }
    2866                 :            :         }
    2867                 :            :         return 0;
    2868                 :            : }
    2869                 :            : 
    2870                 :            : /*
    2871                 :            :  * GTP flags are contained in 1 byte of the format:
    2872                 :            :  * -------------------------------------------
    2873                 :            :  * | bit   | 0 - 2   | 3  | 4   | 5 | 6 | 7  |
    2874                 :            :  * |-----------------------------------------|
    2875                 :            :  * | value | Version | PT | Res | E | S | PN |
    2876                 :            :  * -------------------------------------------
    2877                 :            :  *
    2878                 :            :  * Matching is supported only for GTP flags E, S, PN.
    2879                 :            :  */
    2880                 :            : #define MLX5_GTP_FLAGS_MASK     0x07
    2881                 :            : 
    2882                 :            : /**
    2883                 :            :  * Validate GTP item.
    2884                 :            :  *
    2885                 :            :  * @param[in] dev
    2886                 :            :  *   Pointer to the rte_eth_dev structure.
    2887                 :            :  * @param[in] item
    2888                 :            :  *   Item specification.
    2889                 :            :  * @param[in] item_flags
    2890                 :            :  *   Bit-fields that holds the items detected until now.
    2891                 :            :  * @param[out] error
    2892                 :            :  *   Pointer to error structure.
    2893                 :            :  *
    2894                 :            :  * @return
    2895                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2896                 :            :  */
    2897                 :            : int
    2898                 :          0 : mlx5_flow_dv_validate_item_gtp(struct rte_eth_dev *dev,
    2899                 :            :                                const struct rte_flow_item *item,
    2900                 :            :                                uint64_t item_flags,
    2901                 :            :                                struct rte_flow_error *error)
    2902                 :            : {
    2903                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    2904                 :          0 :         const struct rte_flow_item_gtp *spec = item->spec;
    2905                 :          0 :         const struct rte_flow_item_gtp *mask = item->mask;
    2906                 :          0 :         const struct rte_flow_item_gtp nic_mask = {
    2907                 :            :                 .hdr.gtp_hdr_info = MLX5_GTP_FLAGS_MASK,
    2908                 :            :                 .hdr.msg_type = 0xff,
    2909                 :            :                 .hdr.teid = RTE_BE32(0xffffffff),
    2910                 :            :         };
    2911                 :            : 
    2912         [ #  # ]:          0 :         if (!priv->sh->cdev->config.hca_attr.tunnel_stateless_gtp)
    2913                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2914                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2915                 :            :                                           "GTP support is not enabled");
    2916         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
    2917                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2918                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2919                 :            :                                           "multiple tunnel layers not"
    2920                 :            :                                           " supported");
    2921         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    2922         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP))
    2923                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    2924                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    2925                 :            :                                                   item, "no outer UDP layer found");
    2926                 :            :         }
    2927         [ #  # ]:          0 :         if (!mask)
    2928                 :            :                 mask = &rte_flow_item_gtp_mask;
    2929   [ #  #  #  # ]:          0 :         if (spec && spec->hdr.gtp_hdr_info & ~MLX5_GTP_FLAGS_MASK)
    2930                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2931                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2932                 :            :                                           "Match is supported for GTP"
    2933                 :            :                                           " flags only");
    2934                 :          0 :         return mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2935                 :            :                                          (const uint8_t *)&nic_mask,
    2936                 :            :                                          sizeof(struct rte_flow_item_gtp),
    2937                 :            :                                          MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    2938                 :            : }
    2939                 :            : 
    2940                 :            : /**
    2941                 :            :  * Validate GTP PSC item.
    2942                 :            :  *
    2943                 :            :  * @param[in] item
    2944                 :            :  *   Item specification.
    2945                 :            :  * @param[in] last_item
    2946                 :            :  *   Previous validated item in the pattern items.
    2947                 :            :  * @param[in] gtp_item
    2948                 :            :  *   Previous GTP item specification.
    2949                 :            :  * @param root
    2950                 :            :  *   Whether action is on root table.
    2951                 :            :  * @param[out] error
    2952                 :            :  *   Pointer to error structure.
    2953                 :            :  *
    2954                 :            :  * @return
    2955                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    2956                 :            :  */
    2957                 :            : int
    2958                 :          0 : mlx5_flow_dv_validate_item_gtp_psc(const struct rte_eth_dev *dev,
    2959                 :            :                                    const struct rte_flow_item *item,
    2960                 :            :                                    uint64_t last_item,
    2961                 :            :                                    const struct rte_flow_item *gtp_item,
    2962                 :            :                                    bool root,
    2963                 :            :                                    struct rte_flow_error *error)
    2964                 :            : {
    2965                 :            :         const struct rte_flow_item_gtp *gtp_spec;
    2966                 :            :         const struct rte_flow_item_gtp *gtp_mask;
    2967                 :            :         const struct rte_flow_item_gtp_psc *mask;
    2968                 :          0 :         const struct rte_flow_item_gtp_psc nic_mask = {
    2969                 :            :                 .hdr.type = 0xF,
    2970                 :            :                 .hdr.qfi = 0x3F,
    2971                 :            :         };
    2972                 :            : 
    2973   [ #  #  #  # ]:          0 :         if (!gtp_item || !(last_item & MLX5_FLOW_LAYER_GTP))
    2974                 :          0 :                 return rte_flow_error_set
    2975                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    2976                 :            :                          "GTP PSC item must be preceded with GTP item");
    2977                 :          0 :         gtp_spec = gtp_item->spec;
    2978         [ #  # ]:          0 :         gtp_mask = gtp_item->mask ? gtp_item->mask : &rte_flow_item_gtp_mask;
    2979                 :            :         /* GTP spec and E flag is requested to match zero. */
    2980         [ #  # ]:          0 :         if (gtp_spec &&
    2981                 :          0 :                 (gtp_mask->hdr.gtp_hdr_info &
    2982         [ #  # ]:          0 :                 ~gtp_spec->hdr.gtp_hdr_info & MLX5_GTP_EXT_HEADER_FLAG))
    2983                 :          0 :                 return rte_flow_error_set
    2984                 :            :                         (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
    2985                 :            :                          "GTP E flag must be 1 to match GTP PSC");
    2986         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    2987                 :            :                 /* Check the flow is not created in group zero. */
    2988         [ #  # ]:          0 :                 if (root)
    2989                 :          0 :                         return rte_flow_error_set
    2990                 :            :                                 (error, ENOTSUP,
    2991                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2992                 :            :                                  "GTP PSC is not supported for group 0");
    2993                 :            :                 /* GTP spec is here and E flag is requested to match zero. */
    2994         [ #  # ]:          0 :                 if (!item->spec)
    2995                 :            :                         return 0;
    2996                 :            :         }
    2997         [ #  # ]:          0 :         mask = item->mask ? item->mask : &rte_flow_item_gtp_psc_mask;
    2998                 :          0 :         return mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    2999                 :            :                                          (const uint8_t *)&nic_mask,
    3000                 :            :                                          sizeof(struct rte_flow_item_gtp_psc),
    3001                 :            :                                          MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    3002                 :            : }
    3003                 :            : 
    3004                 :            : /*
    3005                 :            :  * Validate IPV4 item.
    3006                 :            :  * Use existing validation function mlx5_flow_validate_item_ipv4(), and
    3007                 :            :  * add specific validation of fragment_offset field,
    3008                 :            :  *
    3009                 :            :  * @param[in] dev
    3010                 :            :  *   Pointer to the rte_eth_dev structure.
    3011                 :            :  * @param[in] item
    3012                 :            :  *   Item specification.
    3013                 :            :  * @param[in] item_flags
    3014                 :            :  *   Bit-fields that holds the items detected until now.
    3015                 :            :  * @param[in] last_item
    3016                 :            :  *   Previous validated item in the pattern items.
    3017                 :            :  * @param[in] ether_type
    3018                 :            :  *   Type in the ethernet layer header (including dot1q).
    3019                 :            :  * @param[in] acc_mask
    3020                 :            :  *   Default acceptable mask (will be adjusted).
    3021                 :            :  * @param[out] error
    3022                 :            :  *   Pointer to error structure.
    3023                 :            :  *
    3024                 :            :  * @return
    3025                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3026                 :            :  */
    3027                 :            : int
    3028                 :          0 : mlx5_flow_dv_validate_item_ipv4(struct rte_eth_dev *dev,
    3029                 :            :                                 const struct rte_flow_item *item,
    3030                 :            :                                 uint64_t item_flags,
    3031                 :            :                                 uint64_t last_item,
    3032                 :            :                                 uint16_t ether_type,
    3033                 :            :                                 const struct rte_flow_item_ipv4 *acc_mask,
    3034                 :            :                                 struct rte_flow_error *error)
    3035                 :            : {
    3036                 :            :         int ret;
    3037                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3038                 :          0 :         struct mlx5_hca_attr *attr = &priv->sh->cdev->config.hca_attr;
    3039                 :          0 :         const struct rte_flow_item_ipv4 *spec = item->spec;
    3040                 :          0 :         const struct rte_flow_item_ipv4 *last = item->last;
    3041                 :          0 :         const struct rte_flow_item_ipv4 *mask = item->mask;
    3042                 :            :         rte_be16_t fragment_offset_spec = 0;
    3043                 :            :         rte_be16_t fragment_offset_last = 0;
    3044                 :          0 :         struct rte_flow_item_ipv4 actual_ipv4_mask = *acc_mask;
    3045                 :            : 
    3046   [ #  #  #  # ]:          0 :         if (mask && (mask->hdr.version_ihl & RTE_IPV4_HDR_IHL_MASK)) {
    3047                 :          0 :                 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    3048                 :            :                 bool ihl_cap = !tunnel ?
    3049         [ #  # ]:          0 :                                attr->outer_ipv4_ihl : attr->inner_ipv4_ihl;
    3050         [ #  # ]:          0 :                 if (!ihl_cap)
    3051                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3052                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3053                 :            :                                                   item,
    3054                 :            :                                                   "IPV4 ihl offload not supported");
    3055                 :          0 :                 actual_ipv4_mask.hdr.version_ihl = mask->hdr.version_ihl;
    3056                 :            :         }
    3057                 :          0 :         ret = mlx5_flow_validate_item_ipv4(dev, item, item_flags, last_item,
    3058                 :            :                                            ether_type, &actual_ipv4_mask,
    3059                 :            :                                            MLX5_ITEM_RANGE_ACCEPTED, error);
    3060         [ #  # ]:          0 :         if (ret < 0)
    3061                 :            :                 return ret;
    3062         [ #  # ]:          0 :         if (spec && mask)
    3063                 :          0 :                 fragment_offset_spec = spec->hdr.fragment_offset &
    3064                 :          0 :                                        mask->hdr.fragment_offset;
    3065         [ #  # ]:          0 :         if (!fragment_offset_spec)
    3066                 :            :                 return 0;
    3067                 :            :         /*
    3068                 :            :          * spec and mask are valid, enforce using full mask to make sure the
    3069                 :            :          * complete value is used correctly.
    3070                 :            :          */
    3071         [ #  # ]:          0 :         if ((mask->hdr.fragment_offset & RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK))
    3072                 :            :                         != RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK))
    3073                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3074                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_MASK,
    3075                 :            :                                           item, "must use full mask for"
    3076                 :            :                                           " fragment_offset");
    3077                 :            :         /*
    3078                 :            :          * Match on fragment_offset 0x2000 means MF is 1 and frag-offset is 0,
    3079                 :            :          * indicating this is 1st fragment of fragmented packet.
    3080                 :            :          * This is not yet supported in MLX5, return appropriate error message.
    3081                 :            :          */
    3082         [ #  # ]:          0 :         if (fragment_offset_spec == RTE_BE16(RTE_IPV4_HDR_MF_FLAG))
    3083                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3084                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3085                 :            :                                           "match on first fragment not "
    3086                 :            :                                           "supported");
    3087         [ #  # ]:          0 :         if (fragment_offset_spec && !last)
    3088                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3089                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3090                 :            :                                           "specified value not supported");
    3091                 :            :         /* spec and last are valid, validate the specified range. */
    3092                 :          0 :         fragment_offset_last = last->hdr.fragment_offset &
    3093                 :            :                                mask->hdr.fragment_offset;
    3094                 :            :         /*
    3095                 :            :          * Match on fragment_offset spec 0x2001 and last 0x3fff
    3096                 :            :          * means MF is 1 and frag-offset is > 0.
    3097                 :            :          * This packet is fragment 2nd and onward, excluding last.
    3098                 :            :          * This is not yet supported in MLX5, return appropriate
    3099                 :            :          * error message.
    3100                 :            :          */
    3101                 :          0 :         if (fragment_offset_spec == RTE_BE16(RTE_IPV4_HDR_MF_FLAG + 1) &&
    3102         [ #  # ]:          0 :             fragment_offset_last == RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK))
    3103                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3104                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST,
    3105                 :            :                                           last, "match on following "
    3106                 :            :                                           "fragments not supported");
    3107                 :            :         /*
    3108                 :            :          * Match on fragment_offset spec 0x0001 and last 0x1fff
    3109                 :            :          * means MF is 0 and frag-offset is > 0.
    3110                 :            :          * This packet is last fragment of fragmented packet.
    3111                 :            :          * This is not yet supported in MLX5, return appropriate
    3112                 :            :          * error message.
    3113                 :            :          */
    3114                 :          0 :         if (fragment_offset_spec == RTE_BE16(1) &&
    3115         [ #  # ]:          0 :             fragment_offset_last == RTE_BE16(RTE_IPV4_HDR_OFFSET_MASK))
    3116                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3117                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST,
    3118                 :            :                                           last, "match on last "
    3119                 :            :                                           "fragment not supported");
    3120                 :            :         /*
    3121                 :            :          * Match on fragment_offset spec 0x0001 and last 0x3fff
    3122                 :            :          * means MF and/or frag-offset is not 0.
    3123                 :            :          * This is a fragmented packet.
    3124                 :            :          * Other range values are invalid and rejected.
    3125                 :            :          */
    3126                 :          0 :         if (!(fragment_offset_spec == RTE_BE16(1) &&
    3127         [ #  # ]:          0 :               fragment_offset_last == RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK)))
    3128                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3129                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST, last,
    3130                 :            :                                           "specified range not supported");
    3131                 :            :         return 0;
    3132                 :            : }
    3133                 :            : 
    3134                 :            : /**
    3135                 :            :  * Validate IPV6 fragment extension item.
    3136                 :            :  *
    3137                 :            :  * @param[in] item
    3138                 :            :  *   Item specification.
    3139                 :            :  * @param[in] item_flags
    3140                 :            :  *   Bit-fields that holds the items detected until now.
    3141                 :            :  * @param[out] error
    3142                 :            :  *   Pointer to error structure.
    3143                 :            :  *
    3144                 :            :  * @return
    3145                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3146                 :            :  */
    3147                 :            : static int
    3148                 :          0 : flow_dv_validate_item_ipv6_frag_ext(const struct rte_eth_dev *dev,
    3149                 :            :                                     const struct rte_flow_item *item,
    3150                 :            :                                     uint64_t item_flags,
    3151                 :            :                                     struct rte_flow_error *error)
    3152                 :            : {
    3153                 :          0 :         const struct rte_flow_item_ipv6_frag_ext *spec = item->spec;
    3154                 :          0 :         const struct rte_flow_item_ipv6_frag_ext *last = item->last;
    3155                 :          0 :         const struct rte_flow_item_ipv6_frag_ext *mask = item->mask;
    3156                 :            :         rte_be16_t frag_data_spec = 0;
    3157                 :            :         rte_be16_t frag_data_last = 0;
    3158                 :          0 :         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    3159         [ #  # ]:          0 :         const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
    3160                 :            :                                       MLX5_FLOW_LAYER_OUTER_L4;
    3161                 :            :         int ret = 0;
    3162                 :          0 :         struct rte_flow_item_ipv6_frag_ext nic_mask = {
    3163                 :            :                 .hdr = {
    3164                 :            :                         .next_header = 0xff,
    3165                 :            :                         .frag_data = RTE_BE16(0xffff),
    3166                 :            :                 },
    3167                 :            :         };
    3168                 :            : 
    3169         [ #  # ]:          0 :         if (item_flags & l4m)
    3170                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3171                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3172                 :            :                                           "ipv6 fragment extension item cannot "
    3173                 :            :                                           "follow L4 item.");
    3174   [ #  #  #  #  :          0 :         if ((tunnel && !(item_flags & MLX5_FLOW_LAYER_INNER_L3_IPV6)) ||
                   #  # ]
    3175         [ #  # ]:          0 :             (!tunnel && !(item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV6)))
    3176                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3177                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3178                 :            :                                           "ipv6 fragment extension item must "
    3179                 :            :                                           "follow ipv6 item");
    3180         [ #  # ]:          0 :         if (spec && mask)
    3181                 :          0 :                 frag_data_spec = spec->hdr.frag_data & mask->hdr.frag_data;
    3182         [ #  # ]:          0 :         if (!frag_data_spec)
    3183                 :            :                 return 0;
    3184                 :            :         /*
    3185                 :            :          * spec and mask are valid, enforce using full mask to make sure the
    3186                 :            :          * complete value is used correctly.
    3187                 :            :          */
    3188         [ #  # ]:          0 :         if ((mask->hdr.frag_data & RTE_BE16(RTE_IPV6_FRAG_USED_MASK)) !=
    3189                 :            :                                 RTE_BE16(RTE_IPV6_FRAG_USED_MASK))
    3190                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3191                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_MASK,
    3192                 :            :                                           item, "must use full mask for"
    3193                 :            :                                           " frag_data");
    3194                 :            :         /*
    3195                 :            :          * Match on frag_data 0x00001 means M is 1 and frag-offset is 0.
    3196                 :            :          * This is 1st fragment of fragmented packet.
    3197                 :            :          */
    3198         [ #  # ]:          0 :         if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_MF_MASK))
    3199                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3200                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3201                 :            :                                           "match on first fragment not "
    3202                 :            :                                           "supported");
    3203         [ #  # ]:          0 :         if (frag_data_spec && !last)
    3204                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3205                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    3206                 :            :                                           "specified value not supported");
    3207                 :          0 :         ret = mlx5_flow_item_acceptable
    3208                 :            :                                 (dev, item, (const uint8_t *)mask,
    3209                 :            :                                  (const uint8_t *)&nic_mask,
    3210                 :            :                                  sizeof(struct rte_flow_item_ipv6_frag_ext),
    3211                 :            :                                  MLX5_ITEM_RANGE_ACCEPTED, error);
    3212         [ #  # ]:          0 :         if (ret)
    3213                 :            :                 return ret;
    3214                 :            :         /* spec and last are valid, validate the specified range. */
    3215                 :          0 :         frag_data_last = last->hdr.frag_data & mask->hdr.frag_data;
    3216                 :            :         /*
    3217                 :            :          * Match on frag_data spec 0x0009 and last 0xfff9
    3218                 :            :          * means M is 1 and frag-offset is > 0.
    3219                 :            :          * This packet is fragment 2nd and onward, excluding last.
    3220                 :            :          * This is not yet supported in MLX5, return appropriate
    3221                 :            :          * error message.
    3222                 :            :          */
    3223                 :          0 :         if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_FO_ALIGN |
    3224                 :          0 :                                        RTE_IPV6_EHDR_MF_MASK) &&
    3225         [ #  # ]:          0 :             frag_data_last == RTE_BE16(RTE_IPV6_FRAG_USED_MASK))
    3226                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3227                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST,
    3228                 :            :                                           last, "match on following "
    3229                 :            :                                           "fragments not supported");
    3230                 :            :         /*
    3231                 :            :          * Match on frag_data spec 0x0008 and last 0xfff8
    3232                 :            :          * means M is 0 and frag-offset is > 0.
    3233                 :            :          * This packet is last fragment of fragmented packet.
    3234                 :            :          * This is not yet supported in MLX5, return appropriate
    3235                 :            :          * error message.
    3236                 :            :          */
    3237                 :          0 :         if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_FO_ALIGN) &&
    3238         [ #  # ]:          0 :             frag_data_last == RTE_BE16(RTE_IPV6_EHDR_FO_MASK))
    3239                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3240                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_LAST,
    3241                 :            :                                           last, "match on last "
    3242                 :            :                                           "fragment not supported");
    3243                 :            :         /* Other range values are invalid and rejected. */
    3244                 :          0 :         return rte_flow_error_set(error, EINVAL,
    3245                 :            :                                   RTE_FLOW_ERROR_TYPE_ITEM_LAST, last,
    3246                 :            :                                   "specified range not supported");
    3247                 :            : }
    3248                 :            : 
    3249                 :            : /*
    3250                 :            :  * Validate ASO CT item.
    3251                 :            :  *
    3252                 :            :  * @param[in] dev
    3253                 :            :  *   Pointer to the rte_eth_dev structure.
    3254                 :            :  * @param[in] item
    3255                 :            :  *   Item specification.
    3256                 :            :  * @param[in] item_flags
    3257                 :            :  *   Pointer to bit-fields that holds the items detected until now.
    3258                 :            :  * @param[out] error
    3259                 :            :  *   Pointer to error structure.
    3260                 :            :  *
    3261                 :            :  * @return
    3262                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3263                 :            :  */
    3264                 :            : int
    3265                 :          0 : mlx5_flow_dv_validate_item_aso_ct(struct rte_eth_dev *dev,
    3266                 :            :                                   const struct rte_flow_item *item,
    3267                 :            :                                   uint64_t *item_flags,
    3268                 :            :                                   struct rte_flow_error *error)
    3269                 :            : {
    3270                 :          0 :         const struct rte_flow_item_conntrack *spec = item->spec;
    3271                 :          0 :         const struct rte_flow_item_conntrack *mask = item->mask;
    3272                 :            :         uint32_t flags;
    3273                 :            : 
    3274         [ #  # ]:          0 :         if (*item_flags & MLX5_FLOW_LAYER_ASO_CT)
    3275                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3276                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    3277                 :            :                                           "Only one CT is supported");
    3278         [ #  # ]:          0 :         if (!mlx5_hws_active(dev)) {
    3279         [ #  # ]:          0 :                 if (!mask)
    3280                 :            :                         mask = &rte_flow_item_conntrack_mask;
    3281                 :          0 :                 flags = spec->flags & mask->flags;
    3282         [ #  # ]:          0 :                 if ((flags & RTE_FLOW_CONNTRACK_PKT_STATE_VALID) &&
    3283                 :            :                     ((flags & RTE_FLOW_CONNTRACK_PKT_STATE_INVALID) ||
    3284         [ #  # ]:          0 :                      (flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD) ||
    3285                 :            :                      (flags & RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED)))
    3286                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3287                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3288                 :            :                                                   NULL,
    3289                 :            :                                                   "Conflict status bits");
    3290                 :            :         }
    3291                 :            :         /* State change also needs to be considered. */
    3292                 :          0 :         *item_flags |= MLX5_FLOW_LAYER_ASO_CT;
    3293                 :          0 :         return 0;
    3294                 :            : }
    3295                 :            : 
    3296                 :            : /**
    3297                 :            :  * Validate the pop VLAN action.
    3298                 :            :  *
    3299                 :            :  * @param[in] dev
    3300                 :            :  *   Pointer to the rte_eth_dev structure.
    3301                 :            :  * @param[in] action_flags
    3302                 :            :  *   Holds the actions detected until now.
    3303                 :            :  * @param[in] action
    3304                 :            :  *   Pointer to the pop vlan action.
    3305                 :            :  * @param[in] item_flags
    3306                 :            :  *   The items found in this flow rule.
    3307                 :            :  * @param[in] attr
    3308                 :            :  *   Pointer to flow attributes.
    3309                 :            :  * @param[out] error
    3310                 :            :  *   Pointer to error structure.
    3311                 :            :  *
    3312                 :            :  * @return
    3313                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3314                 :            :  */
    3315                 :            : static int
    3316                 :          0 : flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
    3317                 :            :                                  uint64_t action_flags,
    3318                 :            :                                  const struct rte_flow_action *action,
    3319                 :            :                                  uint64_t item_flags,
    3320                 :            :                                  const struct rte_flow_attr *attr,
    3321                 :            :                                  struct rte_flow_error *error)
    3322                 :            : {
    3323                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3324                 :            : 
    3325         [ #  # ]:          0 :         if (!priv->sh->pop_vlan_action)
    3326                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3327                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3328                 :            :                                           NULL,
    3329                 :            :                                           "pop vlan action is not supported");
    3330         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_VLAN_ACTIONS)
    3331                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3332                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3333                 :            :                                           "no support for multiple VLAN "
    3334                 :            :                                           "actions");
    3335                 :            :         /* Pop VLAN with preceding Decap requires inner header with VLAN. */
    3336         [ #  # ]:          0 :         if ((action_flags & MLX5_FLOW_ACTION_DECAP) &&
    3337         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_INNER_VLAN))
    3338                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3339                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3340                 :            :                                           NULL,
    3341                 :            :                                           "cannot pop vlan after decap without "
    3342                 :            :                                           "match on inner vlan in the flow");
    3343                 :            :         /* Pop VLAN without preceding Decap requires outer header with VLAN. */
    3344         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_DECAP) &&
    3345         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
    3346                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3347                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3348                 :            :                                           NULL,
    3349                 :            :                                           "cannot pop vlan without a "
    3350                 :            :                                           "match on (outer) vlan in the flow");
    3351         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3352                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3353                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3354                 :            :                                           "wrong action order, port_id should "
    3355                 :            :                                           "be after pop VLAN action");
    3356   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3357                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3358                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3359                 :            :                                           "pop vlan action for VF representor "
    3360                 :            :                                           "not supported on NIC table");
    3361                 :            :         return 0;
    3362                 :            : }
    3363                 :            : 
    3364                 :            : /**
    3365                 :            :  * Get VLAN default info from vlan match info.
    3366                 :            :  *
    3367                 :            :  * @param[in] items
    3368                 :            :  *   the list of item specifications.
    3369                 :            :  * @param[out] vlan
    3370                 :            :  *   pointer VLAN info to fill to.
    3371                 :            :  *
    3372                 :            :  * @return
    3373                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3374                 :            :  */
    3375                 :            : static void
    3376                 :          0 : flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items,
    3377                 :            :                                   struct rte_vlan_hdr *vlan)
    3378                 :            : {
    3379                 :          0 :         const struct rte_flow_item_vlan nic_mask = {
    3380                 :            :                 .hdr.vlan_tci = RTE_BE16(MLX5DV_FLOW_VLAN_PCP_MASK |
    3381                 :            :                                 MLX5DV_FLOW_VLAN_VID_MASK),
    3382                 :            :                 .hdr.eth_proto = RTE_BE16(0xffff),
    3383                 :            :         };
    3384                 :            : 
    3385         [ #  # ]:          0 :         if (items == NULL)
    3386                 :          0 :                 return;
    3387         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    3388                 :          0 :                 int type = items->type;
    3389                 :            : 
    3390                 :          0 :                 if (type == RTE_FLOW_ITEM_TYPE_VLAN ||
    3391         [ #  # ]:          0 :                     type == MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
    3392                 :            :                         break;
    3393                 :            :         }
    3394         [ #  # ]:          0 :         if (items->type != RTE_FLOW_ITEM_TYPE_END) {
    3395                 :          0 :                 const struct rte_flow_item_vlan *vlan_m = items->mask;
    3396                 :          0 :                 const struct rte_flow_item_vlan *vlan_v = items->spec;
    3397                 :            : 
    3398                 :            :                 /* If VLAN item in pattern doesn't contain data, return here. */
    3399         [ #  # ]:          0 :                 if (!vlan_v)
    3400                 :            :                         return;
    3401         [ #  # ]:          0 :                 if (!vlan_m)
    3402                 :            :                         vlan_m = &nic_mask;
    3403                 :            :                 /* Only full match values are accepted */
    3404         [ #  # ]:          0 :                 if ((vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) ==
    3405                 :            :                      MLX5DV_FLOW_VLAN_PCP_MASK_BE) {
    3406                 :          0 :                         vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK;
    3407                 :          0 :                         vlan->vlan_tci |=
    3408         [ #  # ]:          0 :                                 rte_be_to_cpu_16(vlan_v->hdr.vlan_tci &
    3409                 :            :                                                  MLX5DV_FLOW_VLAN_PCP_MASK_BE);
    3410                 :            :                 }
    3411         [ #  # ]:          0 :                 if ((vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) ==
    3412                 :            :                      MLX5DV_FLOW_VLAN_VID_MASK_BE) {
    3413                 :          0 :                         vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_VID_MASK;
    3414                 :          0 :                         vlan->vlan_tci |=
    3415         [ #  # ]:          0 :                                 rte_be_to_cpu_16(vlan_v->hdr.vlan_tci &
    3416                 :            :                                                  MLX5DV_FLOW_VLAN_VID_MASK_BE);
    3417                 :            :                 }
    3418         [ #  # ]:          0 :                 if (vlan_m->hdr.eth_proto == nic_mask.hdr.eth_proto)
    3419         [ #  # ]:          0 :                         vlan->eth_proto = rte_be_to_cpu_16(vlan_v->hdr.eth_proto &
    3420                 :            :                                                            vlan_m->hdr.eth_proto);
    3421                 :            :         }
    3422                 :            : }
    3423                 :            : 
    3424                 :            : /**
    3425                 :            :  * Validate the push VLAN action.
    3426                 :            :  *
    3427                 :            :  * @param[in] dev
    3428                 :            :  *   Pointer to the rte_eth_dev structure.
    3429                 :            :  * @param[in] action_flags
    3430                 :            :  *   Holds the actions detected until now.
    3431                 :            :  * @param[in] item_flags
    3432                 :            :  *   The items found in this flow rule.
    3433                 :            :  * @param[in] action
    3434                 :            :  *   Pointer to the action structure.
    3435                 :            :  * @param[in] attr
    3436                 :            :  *   Pointer to flow attributes
    3437                 :            :  * @param[out] error
    3438                 :            :  *   Pointer to error structure.
    3439                 :            :  *
    3440                 :            :  * @return
    3441                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3442                 :            :  */
    3443                 :            : static int
    3444                 :          0 : flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev,
    3445                 :            :                                   uint64_t action_flags,
    3446                 :            :                                   const struct rte_flow_item_vlan *vlan_m,
    3447                 :            :                                   const struct rte_flow_action *action,
    3448                 :            :                                   const struct rte_flow_attr *attr,
    3449                 :            :                                   struct rte_flow_error *error)
    3450                 :            : {
    3451                 :          0 :         const struct rte_flow_action_of_push_vlan *push_vlan = action->conf;
    3452                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3453                 :            : 
    3454         [ #  # ]:          0 :         if (push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_VLAN) &&
    3455                 :            :             push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_QINQ))
    3456                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3457                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3458                 :            :                                           "invalid vlan ethertype");
    3459         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3460                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3461                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3462                 :            :                                           "wrong action order, port_id should "
    3463                 :            :                                           "be after push VLAN");
    3464   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3465                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3466                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3467                 :            :                                           "push vlan action for VF representor "
    3468                 :            :                                           "not supported on NIC table");
    3469         [ #  # ]:          0 :         if (vlan_m &&
    3470   [ #  #  #  # ]:          0 :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) &&
    3471                 :            :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) !=
    3472                 :          0 :                 MLX5DV_FLOW_VLAN_PCP_MASK_BE &&
    3473   [ #  #  #  # ]:          0 :             !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP) &&
    3474                 :          0 :             !(mlx5_flow_find_action
    3475                 :            :                 (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP)))
    3476                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3477                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3478                 :            :                                           "not full match mask on VLAN PCP and "
    3479                 :            :                                           "there is no of_set_vlan_pcp action, "
    3480                 :            :                                           "push VLAN action cannot figure out "
    3481                 :            :                                           "PCP value");
    3482         [ #  # ]:          0 :         if (vlan_m &&
    3483   [ #  #  #  # ]:          0 :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) &&
    3484                 :            :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) !=
    3485                 :          0 :                 MLX5DV_FLOW_VLAN_VID_MASK_BE &&
    3486   [ #  #  #  # ]:          0 :             !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID) &&
    3487                 :          0 :             !(mlx5_flow_find_action
    3488                 :            :                 (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)))
    3489                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3490                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3491                 :            :                                           "not full match mask on VLAN VID and "
    3492                 :            :                                           "there is no of_set_vlan_vid action, "
    3493                 :            :                                           "push VLAN action cannot figure out "
    3494                 :            :                                           "VID value");
    3495                 :            :         (void)attr;
    3496                 :            :         return 0;
    3497                 :            : }
    3498                 :            : 
    3499                 :            : /**
    3500                 :            :  * Validate the set VLAN PCP.
    3501                 :            :  *
    3502                 :            :  * @param[in] action_flags
    3503                 :            :  *   Holds the actions detected until now.
    3504                 :            :  * @param[in] actions
    3505                 :            :  *   Pointer to the list of actions remaining in the flow rule.
    3506                 :            :  * @param[out] error
    3507                 :            :  *   Pointer to error structure.
    3508                 :            :  *
    3509                 :            :  * @return
    3510                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3511                 :            :  */
    3512                 :            : static int
    3513                 :          0 : flow_dv_validate_action_set_vlan_pcp(uint64_t action_flags,
    3514                 :            :                                      const struct rte_flow_action actions[],
    3515                 :            :                                      struct rte_flow_error *error)
    3516                 :            : {
    3517                 :            :         const struct rte_flow_action *action = actions;
    3518                 :          0 :         const struct rte_flow_action_of_set_vlan_pcp *conf = action->conf;
    3519                 :            : 
    3520         [ #  # ]:          0 :         if (conf->vlan_pcp > 7)
    3521                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3522                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3523                 :            :                                           "VLAN PCP value is too big");
    3524         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN))
    3525                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3526                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3527                 :            :                                           "set VLAN PCP action must follow "
    3528                 :            :                                           "the push VLAN action");
    3529         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP)
    3530                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3531                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3532                 :            :                                           "Multiple VLAN PCP modification are "
    3533                 :            :                                           "not supported");
    3534         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3535                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3536                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3537                 :            :                                           "wrong action order, port_id should "
    3538                 :            :                                           "be after set VLAN PCP");
    3539                 :            :         return 0;
    3540                 :            : }
    3541                 :            : 
    3542                 :            : /**
    3543                 :            :  * Validate the set VLAN VID.
    3544                 :            :  *
    3545                 :            :  * @param[in] item_flags
    3546                 :            :  *   Holds the items detected in this rule.
    3547                 :            :  * @param[in] action_flags
    3548                 :            :  *   Holds the actions detected until now.
    3549                 :            :  * @param[in] actions
    3550                 :            :  *   Pointer to the list of actions remaining in the flow rule.
    3551                 :            :  * @param[out] error
    3552                 :            :  *   Pointer to error structure.
    3553                 :            :  *
    3554                 :            :  * @return
    3555                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3556                 :            :  */
    3557                 :            : static int
    3558                 :          0 : flow_dv_validate_action_set_vlan_vid(uint64_t item_flags,
    3559                 :            :                                      uint64_t action_flags,
    3560                 :            :                                      const struct rte_flow_action actions[],
    3561                 :            :                                      struct rte_flow_error *error)
    3562                 :            : {
    3563                 :            :         const struct rte_flow_action *action = actions;
    3564                 :          0 :         const struct rte_flow_action_of_set_vlan_vid *conf = action->conf;
    3565                 :            : 
    3566   [ #  #  #  # ]:          0 :         if (rte_be_to_cpu_16(conf->vlan_vid) > 0xFFE)
    3567                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3568                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3569                 :            :                                           "VLAN VID value is too big");
    3570         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) &&
    3571         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
    3572                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3573                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3574                 :            :                                           "set VLAN VID action must follow push"
    3575                 :            :                                           " VLAN action or match on VLAN item");
    3576         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID)
    3577                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3578                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3579                 :            :                                           "Multiple VLAN VID modifications are "
    3580                 :            :                                           "not supported");
    3581         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3582                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3583                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3584                 :            :                                           "wrong action order, port_id should "
    3585                 :            :                                           "be after set VLAN VID");
    3586                 :            :         return 0;
    3587                 :            : }
    3588                 :            : 
    3589                 :            : /*
    3590                 :            :  * Validate the FLAG action.
    3591                 :            :  *
    3592                 :            :  * @param[in] dev
    3593                 :            :  *   Pointer to the rte_eth_dev structure.
    3594                 :            :  * @param[in] action_flags
    3595                 :            :  *   Holds the actions detected until now.
    3596                 :            :  * @param[in] attr
    3597                 :            :  *   Pointer to flow attributes
    3598                 :            :  * @param[out] error
    3599                 :            :  *   Pointer to error structure.
    3600                 :            :  *
    3601                 :            :  * @return
    3602                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3603                 :            :  */
    3604                 :            : static int
    3605                 :          0 : flow_dv_validate_action_flag(struct rte_eth_dev *dev,
    3606                 :            :                              uint64_t action_flags,
    3607                 :            :                              const struct rte_flow_attr *attr,
    3608                 :            :                              struct rte_flow_error *error)
    3609                 :            : {
    3610                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3611                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3612                 :            :         int ret;
    3613                 :            : 
    3614                 :            :         /* Fall back if no extended metadata register support. */
    3615         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
    3616                 :          0 :                 return mlx5_flow_validate_action_flag(action_flags, attr,
    3617                 :            :                                                       error);
    3618                 :            :         /* Extensive metadata mode requires registers. */
    3619         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3620                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3621                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3622                 :            :                                           "no metadata registers "
    3623                 :            :                                           "to support flag action");
    3624         [ #  # ]:          0 :         if (!(priv->sh->dv_mark_mask & MLX5_FLOW_MARK_DEFAULT))
    3625                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3626                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3627                 :            :                                           "extended metadata register"
    3628                 :            :                                           " isn't available");
    3629                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    3630         [ #  # ]:          0 :         if (ret < 0)
    3631                 :            :                 return ret;
    3632                 :            :         MLX5_ASSERT(ret > 0);
    3633         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_MARK)
    3634                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3635                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3636                 :            :                                           "can't mark and flag in same flow");
    3637         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_FLAG)
    3638                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3639                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3640                 :            :                                           "can't have 2 flag"
    3641                 :            :                                           " actions in same flow");
    3642                 :            :         return 0;
    3643                 :            : }
    3644                 :            : 
    3645                 :            : /**
    3646                 :            :  * Validate MARK action.
    3647                 :            :  *
    3648                 :            :  * @param[in] dev
    3649                 :            :  *   Pointer to the rte_eth_dev structure.
    3650                 :            :  * @param[in] action
    3651                 :            :  *   Pointer to action.
    3652                 :            :  * @param[in] action_flags
    3653                 :            :  *   Holds the actions detected until now.
    3654                 :            :  * @param[in] attr
    3655                 :            :  *   Pointer to flow attributes
    3656                 :            :  * @param[out] error
    3657                 :            :  *   Pointer to error structure.
    3658                 :            :  *
    3659                 :            :  * @return
    3660                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3661                 :            :  */
    3662                 :            : static int
    3663                 :          0 : flow_dv_validate_action_mark(struct rte_eth_dev *dev,
    3664                 :            :                              const struct rte_flow_action *action,
    3665                 :            :                              uint64_t action_flags,
    3666                 :            :                              const struct rte_flow_attr *attr,
    3667                 :            :                              struct rte_flow_error *error)
    3668                 :            : {
    3669                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3670                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3671         [ #  # ]:          0 :         const struct rte_flow_action_mark *mark = action->conf;
    3672                 :            :         int ret;
    3673                 :            : 
    3674         [ #  # ]:          0 :         if (is_tunnel_offload_active(dev))
    3675                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3676                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3677                 :            :                                           "no mark action "
    3678                 :            :                                           "if tunnel offload active");
    3679                 :            :         /* Fall back if no extended metadata register support. */
    3680         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
    3681                 :          0 :                 return mlx5_flow_validate_action_mark(dev, action, action_flags,
    3682                 :            :                                                       attr, error);
    3683                 :            :         /* Extensive metadata mode requires registers. */
    3684         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3685                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3686                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3687                 :            :                                           "no metadata registers "
    3688                 :            :                                           "to support mark action");
    3689         [ #  # ]:          0 :         if (!priv->sh->dv_mark_mask)
    3690                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3691                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3692                 :            :                                           "extended metadata register"
    3693                 :            :                                           " isn't available");
    3694                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    3695         [ #  # ]:          0 :         if (ret < 0)
    3696                 :            :                 return ret;
    3697                 :            :         MLX5_ASSERT(ret > 0);
    3698         [ #  # ]:          0 :         if (!mark)
    3699                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3700                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3701                 :            :                                           "configuration cannot be null");
    3702         [ #  # ]:          0 :         if (mark->id >= (MLX5_FLOW_MARK_MAX & priv->sh->dv_mark_mask))
    3703                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3704                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    3705                 :          0 :                                           &mark->id,
    3706                 :            :                                           "mark id exceeds the limit");
    3707         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_FLAG)
    3708                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3709                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3710                 :            :                                           "can't flag and mark in same flow");
    3711         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_MARK)
    3712                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3713                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3714                 :            :                                           "can't have 2 mark actions in same"
    3715                 :            :                                           " flow");
    3716                 :            :         return 0;
    3717                 :            : }
    3718                 :            : 
    3719                 :            : /**
    3720                 :            :  * Validate SET_META action.
    3721                 :            :  *
    3722                 :            :  * @param[in] dev
    3723                 :            :  *   Pointer to the rte_eth_dev structure.
    3724                 :            :  * @param[in] action
    3725                 :            :  *   Pointer to the action structure.
    3726                 :            :  * @param[in] action_flags
    3727                 :            :  *   Holds the actions detected until now.
    3728                 :            :  * @param[in] attr
    3729                 :            :  *   Pointer to flow attributes
    3730                 :            :  * @param[out] error
    3731                 :            :  *   Pointer to error structure.
    3732                 :            :  *
    3733                 :            :  * @return
    3734                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3735                 :            :  */
    3736                 :            : static int
    3737                 :          0 : flow_dv_validate_action_set_meta(struct rte_eth_dev *dev,
    3738                 :            :                                  const struct rte_flow_action *action,
    3739                 :            :                                  uint64_t action_flags __rte_unused,
    3740                 :            :                                  const struct rte_flow_attr *attr,
    3741                 :            :                                  struct rte_flow_error *error)
    3742                 :            : {
    3743                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3744                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3745                 :            :         const struct rte_flow_action_set_meta *conf;
    3746                 :            :         uint32_t nic_mask = UINT32_MAX;
    3747                 :            :         int reg;
    3748                 :            : 
    3749   [ #  #  #  # ]:          0 :         if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    3750                 :          0 :             !mlx5_flow_ext_mreg_supported(dev))
    3751                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3752                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3753                 :            :                                           "extended metadata register"
    3754                 :            :                                           " isn't supported");
    3755                 :          0 :         reg = flow_dv_get_metadata_reg(dev, attr, error);
    3756         [ #  # ]:          0 :         if (reg < 0)
    3757                 :            :                 return reg;
    3758         [ #  # ]:          0 :         if (reg == REG_NON)
    3759                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3760                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3761                 :            :                                           "unavailable extended metadata register");
    3762         [ #  # ]:          0 :         if (reg != REG_A && reg != REG_B) {
    3763                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    3764                 :            : 
    3765                 :          0 :                 nic_mask = priv->sh->dv_meta_mask;
    3766                 :            :         }
    3767         [ #  # ]:          0 :         if (!(action->conf))
    3768                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3769                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3770                 :            :                                           "configuration cannot be null");
    3771                 :            :         conf = (const struct rte_flow_action_set_meta *)action->conf;
    3772         [ #  # ]:          0 :         if (!conf->mask)
    3773                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3774                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3775                 :            :                                           "zero mask doesn't have any effect");
    3776         [ #  # ]:          0 :         if (conf->mask & ~nic_mask)
    3777                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3778                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3779                 :            :                                           "meta data must be within reg C0");
    3780                 :            :         return 0;
    3781                 :            : }
    3782                 :            : 
    3783                 :            : /**
    3784                 :            :  * Validate SET_TAG action.
    3785                 :            :  *
    3786                 :            :  * @param[in] dev
    3787                 :            :  *   Pointer to the rte_eth_dev structure.
    3788                 :            :  * @param[in] action
    3789                 :            :  *   Pointer to the action structure.
    3790                 :            :  * @param[in] action_flags
    3791                 :            :  *   Holds the actions detected until now.
    3792                 :            :  * @param[in] attr
    3793                 :            :  *   Pointer to flow attributes
    3794                 :            :  * @param[out] error
    3795                 :            :  *   Pointer to error structure.
    3796                 :            :  *
    3797                 :            :  * @return
    3798                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3799                 :            :  */
    3800                 :            : static int
    3801                 :          0 : flow_dv_validate_action_set_tag(struct rte_eth_dev *dev,
    3802                 :            :                                 const struct rte_flow_action *action,
    3803                 :            :                                 uint64_t action_flags,
    3804                 :            :                                 const struct rte_flow_attr *attr,
    3805                 :            :                                 struct rte_flow_error *error)
    3806                 :            : {
    3807                 :            :         const struct rte_flow_action_set_tag *conf;
    3808                 :            :         const uint64_t terminal_action_flags =
    3809                 :            :                 MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
    3810                 :            :                 MLX5_FLOW_ACTION_RSS;
    3811                 :            :         int ret;
    3812                 :            : 
    3813         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3814                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3815                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3816                 :            :                                           "extensive metadata register"
    3817                 :            :                                           " isn't supported");
    3818         [ #  # ]:          0 :         if (!(action->conf))
    3819                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3820                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3821                 :            :                                           "configuration cannot be null");
    3822                 :            :         conf = (const struct rte_flow_action_set_tag *)action->conf;
    3823         [ #  # ]:          0 :         if (!conf->mask)
    3824                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3825                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3826                 :            :                                           "zero mask doesn't have any effect");
    3827                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, conf->index, error);
    3828         [ #  # ]:          0 :         if (ret < 0)
    3829                 :            :                 return ret;
    3830   [ #  #  #  # ]:          0 :         if (attr->ingress && (action_flags & terminal_action_flags))
    3831                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3832                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3833                 :            :                                           "set_tag has no effect"
    3834                 :            :                                           " with terminal actions");
    3835                 :            :         return 0;
    3836                 :            : }
    3837                 :            : 
    3838                 :            : /**
    3839                 :            :  * Indicates whether ASO aging is supported.
    3840                 :            :  *
    3841                 :            :  * @param[in] priv
    3842                 :            :  *   Pointer to device private context structure.
    3843                 :            :  * @param[in] root
    3844                 :            :  *   Whether action is on root table.
    3845                 :            :  *
    3846                 :            :  * @return
    3847                 :            :  *   True when ASO aging is supported, false otherwise.
    3848                 :            :  */
    3849                 :            : static inline bool
    3850                 :            : flow_hit_aso_supported(const struct mlx5_priv *priv, bool root)
    3851                 :            : {
    3852                 :            :         MLX5_ASSERT(priv);
    3853   [ #  #  #  #  :          0 :         return (priv->sh->flow_hit_aso_en && !root);
          #  #  #  #  #  
                      # ]
    3854                 :            : }
    3855                 :            : 
    3856                 :            : /**
    3857                 :            :  * Validate count action.
    3858                 :            :  *
    3859                 :            :  * @param[in] dev
    3860                 :            :  *   Pointer to rte_eth_dev structure.
    3861                 :            :  * @param[in] shared
    3862                 :            :  *   Indicator if action is shared.
    3863                 :            :  * @param[in] action_flags
    3864                 :            :  *   Holds the actions detected until now.
    3865                 :            :  * @param[in] root
    3866                 :            :  *   Whether action is on root table.
    3867                 :            :  * @param[out] error
    3868                 :            :  *   Pointer to error structure.
    3869                 :            :  *
    3870                 :            :  * @return
    3871                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3872                 :            :  */
    3873                 :            : static int
    3874                 :          0 : flow_dv_validate_action_count(struct rte_eth_dev *dev, bool shared,
    3875                 :            :                               uint64_t action_flags,
    3876                 :            :                               bool root,
    3877                 :            :                               struct rte_flow_error *error)
    3878                 :            : {
    3879                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3880                 :            : 
    3881         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
    3882                 :          0 :                 goto notsup_err;
    3883         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_COUNT)
    3884                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3885                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3886                 :            :                                           "duplicate count actions set");
    3887   [ #  #  #  #  :          0 :         if (shared && (action_flags & MLX5_FLOW_ACTION_AGE) &&
                   #  # ]
    3888                 :            :             !flow_hit_aso_supported(priv, root))
    3889                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3890                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3891                 :            :                                           "old age and indirect count combination is not supported");
    3892                 :            : #ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
    3893                 :            :         return 0;
    3894                 :            : #endif
    3895                 :            : notsup_err:
    3896                 :          0 :         return rte_flow_error_set
    3897                 :            :                       (error, ENOTSUP,
    3898                 :            :                        RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3899                 :            :                        NULL,
    3900                 :            :                        "count action not supported");
    3901                 :            : }
    3902                 :            : 
    3903                 :            : /**
    3904                 :            :  * Validate the L2 encap action.
    3905                 :            :  *
    3906                 :            :  * @param[in] dev
    3907                 :            :  *   Pointer to the rte_eth_dev structure.
    3908                 :            :  * @param[in] action_flags
    3909                 :            :  *   Holds the actions detected until now.
    3910                 :            :  * @param[in] action
    3911                 :            :  *   Pointer to the action structure.
    3912                 :            :  * @param[in] attr
    3913                 :            :  *   Pointer to flow attributes.
    3914                 :            :  * @param[out] error
    3915                 :            :  *   Pointer to error structure.
    3916                 :            :  *
    3917                 :            :  * @return
    3918                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3919                 :            :  */
    3920                 :            : int
    3921                 :          0 : mlx5_flow_dv_validate_action_l2_encap(struct rte_eth_dev *dev,
    3922                 :            :                                       uint64_t action_flags,
    3923                 :            :                                       const struct rte_flow_action *action,
    3924                 :            :                                       const struct rte_flow_attr *attr,
    3925                 :            :                                       struct rte_flow_error *error)
    3926                 :            : {
    3927                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3928                 :            : 
    3929         [ #  # ]:          0 :         if (!(action->conf))
    3930                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3931                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3932                 :            :                                           "configuration cannot be null");
    3933         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    3934                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3935                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3936                 :            :                                           "can only have a single encap action "
    3937                 :            :                                           "in a flow");
    3938   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3939                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3940                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3941                 :            :                                           "encap action for VF representor "
    3942                 :            :                                           "not supported on NIC table");
    3943                 :            :         return 0;
    3944                 :            : }
    3945                 :            : 
    3946                 :            : /**
    3947                 :            :  * Validate a decap action.
    3948                 :            :  *
    3949                 :            :  * @param[in] dev
    3950                 :            :  *   Pointer to the rte_eth_dev structure.
    3951                 :            :  * @param[in] action_flags
    3952                 :            :  *   Holds the actions detected until now.
    3953                 :            :  * @param[in] action
    3954                 :            :  *   Pointer to the action structure.
    3955                 :            :  * @param[in] item_flags
    3956                 :            :  *   Holds the items detected.
    3957                 :            :  * @param[in] attr
    3958                 :            :  *   Pointer to flow attributes
    3959                 :            :  * @param[out] error
    3960                 :            :  *   Pointer to error structure.
    3961                 :            :  *
    3962                 :            :  * @return
    3963                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3964                 :            :  */
    3965                 :            : int
    3966                 :          0 : mlx5_flow_dv_validate_action_decap(struct rte_eth_dev *dev,
    3967                 :            :                                    uint64_t action_flags,
    3968                 :            :                                    const struct rte_flow_action *action,
    3969                 :            :                                    const uint64_t item_flags,
    3970                 :            :                                    const struct rte_flow_attr *attr,
    3971                 :            :                                    struct rte_flow_error *error)
    3972                 :            : {
    3973                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3974                 :            : 
    3975         [ #  # ]:          0 :         if (priv->sh->cdev->config.hca_attr.scatter_fcs_w_decap_disable &&
    3976         [ #  # ]:          0 :             !priv->sh->config.decap_en)
    3977                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3978                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3979                 :            :                                           "decap is not enabled");
    3980         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_XCAP_ACTIONS)
    3981                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3982                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3983         [ #  # ]:          0 :                                           action_flags &
    3984                 :            :                                           MLX5_FLOW_ACTION_DECAP ? "can only "
    3985                 :            :                                           "have a single decap action" : "decap "
    3986                 :            :                                           "after encap is not supported");
    3987         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)
    3988                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3989                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3990                 :            :                                           "can't have decap action after"
    3991                 :            :                                           " modify action");
    3992         [ #  # ]:          0 :         if (attr->egress)
    3993                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3994                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
    3995                 :            :                                           NULL,
    3996                 :            :                                           "decap action not supported for "
    3997                 :            :                                           "egress");
    3998   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3999                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4000                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4001                 :            :                                           "decap action for VF representor "
    4002                 :            :                                           "not supported on NIC table");
    4003         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP &&
    4004         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_VXLAN))
    4005                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4006                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4007                 :            :                                 "VXLAN item should be present for VXLAN decap");
    4008                 :            :         return 0;
    4009                 :            : }
    4010                 :            : 
    4011                 :            : const struct rte_flow_action_raw_decap empty_decap = {.data = NULL, .size = 0,};
    4012                 :            : 
    4013                 :            : /**
    4014                 :            :  * Validate the raw encap and decap actions.
    4015                 :            :  *
    4016                 :            :  * @param[in] dev
    4017                 :            :  *   Pointer to the rte_eth_dev structure.
    4018                 :            :  * @param[in] decap
    4019                 :            :  *   Pointer to the decap action.
    4020                 :            :  * @param[in] encap
    4021                 :            :  *   Pointer to the encap action.
    4022                 :            :  * @param[in] attr
    4023                 :            :  *   Pointer to flow attributes
    4024                 :            :  * @param[in/out] action_flags
    4025                 :            :  *   Holds the actions detected until now.
    4026                 :            :  * @param[out] actions_n
    4027                 :            :  *   pointer to the number of actions counter.
    4028                 :            :  * @param[in] action
    4029                 :            :  *   Pointer to the action structure.
    4030                 :            :  * @param[in] item_flags
    4031                 :            :  *   Holds the items detected.
    4032                 :            :  * @param[out] error
    4033                 :            :  *   Pointer to error structure.
    4034                 :            :  *
    4035                 :            :  * @return
    4036                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4037                 :            :  */
    4038                 :            : int
    4039                 :          0 : mlx5_flow_dv_validate_action_raw_encap_decap
    4040                 :            :         (struct rte_eth_dev *dev,
    4041                 :            :          const struct rte_flow_action_raw_decap *decap,
    4042                 :            :          const struct rte_flow_action_raw_encap *encap,
    4043                 :            :          const struct rte_flow_attr *attr, uint64_t *action_flags,
    4044                 :            :          int *actions_n, const struct rte_flow_action *action,
    4045                 :            :          uint64_t item_flags, struct rte_flow_error *error)
    4046                 :            : {
    4047                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    4048                 :            :         int ret;
    4049                 :            : 
    4050         [ #  # ]:          0 :         if (encap) {
    4051         [ #  # ]:          0 :                 if (!mlx5_hws_active(dev)) {
    4052   [ #  #  #  # ]:          0 :                         if (!encap->size || !encap->data)
    4053                 :          0 :                                 return rte_flow_error_set
    4054                 :            :                                         (error, EINVAL,
    4055                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION, NULL, "raw encap data cannot be empty");
    4056                 :            :                 } else {
    4057         [ #  # ]:          0 :                         if (!encap->size)
    4058                 :          0 :                                 return rte_flow_error_set
    4059                 :            :                                         (error, EINVAL,
    4060                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION, NULL, "raw encap size cannot be 0");
    4061                 :            :                 }
    4062                 :            :         }
    4063         [ #  # ]:          0 :         if (decap && encap) {
    4064         [ #  # ]:          0 :                 if (decap->size <= MLX5_ENCAPSULATION_DECISION_SIZE &&
    4065         [ #  # ]:          0 :                     encap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
    4066                 :            :                         /* L3 encap. */
    4067                 :            :                         decap = NULL;
    4068         [ #  # ]:          0 :                 else if (encap->size <=
    4069         [ #  # ]:          0 :                            MLX5_ENCAPSULATION_DECISION_SIZE &&
    4070                 :            :                            decap->size >
    4071                 :            :                            MLX5_ENCAPSULATION_DECISION_SIZE)
    4072                 :            :                         /* L3 decap. */
    4073                 :            :                         encap = NULL;
    4074         [ #  # ]:          0 :                 else if (encap->size >
    4075         [ #  # ]:          0 :                            MLX5_ENCAPSULATION_DECISION_SIZE &&
    4076                 :            :                            decap->size >
    4077                 :            :                            MLX5_ENCAPSULATION_DECISION_SIZE)
    4078                 :            :                         /* 2 L2 actions: encap and decap. */
    4079                 :            :                         ;
    4080                 :            :                 else
    4081                 :          0 :                         return rte_flow_error_set(error,
    4082                 :            :                                 ENOTSUP,
    4083                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4084                 :            :                                 NULL, "unsupported too small "
    4085                 :            :                                 "raw decap and too small raw "
    4086                 :            :                                 "encap combination");
    4087                 :            :         }
    4088         [ #  # ]:          0 :         if (decap) {
    4089                 :          0 :                 ret = mlx5_flow_dv_validate_action_decap(dev, *action_flags,
    4090                 :            :                                                          action,
    4091                 :            :                                                          item_flags, attr,
    4092                 :            :                                                          error);
    4093         [ #  # ]:          0 :                 if (ret < 0)
    4094                 :            :                         return ret;
    4095                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_DECAP;
    4096                 :          0 :                 ++(*actions_n);
    4097                 :            :         }
    4098         [ #  # ]:          0 :         if (encap) {
    4099         [ #  # ]:          0 :                 if (encap->size <= MLX5_ENCAPSULATION_DECISION_SIZE)
    4100                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    4101                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4102                 :            :                                                   NULL,
    4103                 :            :                                                   "small raw encap size");
    4104         [ #  # ]:          0 :                 if (*action_flags & MLX5_FLOW_ACTION_ENCAP)
    4105                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4106                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4107                 :            :                                                   NULL,
    4108                 :            :                                                   "more than one encap action");
    4109   [ #  #  #  # ]:          0 :                 if (!attr->transfer && priv->representor)
    4110                 :          0 :                         return rte_flow_error_set
    4111                 :            :                                         (error, ENOTSUP,
    4112                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4113                 :            :                                          "encap action for VF representor "
    4114                 :            :                                          "not supported on NIC table");
    4115                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_ENCAP;
    4116                 :          0 :                 ++(*actions_n);
    4117                 :            :         }
    4118                 :            :         return 0;
    4119                 :            : }
    4120                 :            : 
    4121                 :            : /*
    4122                 :            :  * Validate the ASO CT action.
    4123                 :            :  *
    4124                 :            :  * @param[in] dev
    4125                 :            :  *   Pointer to the rte_eth_dev structure.
    4126                 :            :  * @param[in] action_flags
    4127                 :            :  *   Holds the actions detected until now.
    4128                 :            :  * @param[in] item_flags
    4129                 :            :  *   The items found in this flow rule.
    4130                 :            :  * @param root
    4131                 :            :  *   Whether action is on root table.
    4132                 :            :  * @param[out] error
    4133                 :            :  *   Pointer to error structure.
    4134                 :            :  *
    4135                 :            :  * @return
    4136                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4137                 :            :  */
    4138                 :            : int
    4139                 :          0 : mlx5_flow_dv_validate_action_aso_ct(struct rte_eth_dev *dev,
    4140                 :            :                                     uint64_t action_flags,
    4141                 :            :                                     uint64_t item_flags,
    4142                 :            :                                     bool root,
    4143                 :            :                                     struct rte_flow_error *error)
    4144                 :            : {
    4145                 :            :         RTE_SET_USED(dev);
    4146                 :            : 
    4147         [ #  # ]:          0 :         if (root)
    4148                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4149                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4150                 :            :                                           NULL,
    4151                 :            :                                           "Only support non-root table");
    4152         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_FATE_ACTIONS)
    4153                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4154                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4155                 :            :                                           "CT cannot follow a fate action");
    4156         [ #  # ]:          0 :         if ((action_flags & MLX5_FLOW_ACTION_METER) ||
    4157                 :            :             (action_flags & MLX5_FLOW_ACTION_AGE)) {
    4158         [ #  # ]:          0 :                 if (!mlx5_hws_active(dev))
    4159                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4160                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4161                 :            :                                                   NULL, "Only one ASO action is supported");
    4162                 :            :         }
    4163         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    4164                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4165                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4166                 :            :                                           "Encap cannot exist before CT");
    4167         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP))
    4168                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4169                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4170                 :            :                                           "Not a outer TCP packet");
    4171                 :            :         return 0;
    4172                 :            : }
    4173                 :            : 
    4174                 :            : /**
    4175                 :            :  * Validate METER_COLOR item.
    4176                 :            :  *
    4177                 :            :  * @param[in] dev
    4178                 :            :  *   Pointer to the rte_eth_dev structure.
    4179                 :            :  * @param[in] item
    4180                 :            :  *   Item specification.
    4181                 :            :  * @param[in] attr
    4182                 :            :  *   Attributes of flow that includes this item.
    4183                 :            :  * @param[out] error
    4184                 :            :  *   Pointer to error structure.
    4185                 :            :  *
    4186                 :            :  * @return
    4187                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4188                 :            :  */
    4189                 :            : static int
    4190                 :          0 : flow_dv_validate_item_meter_color(struct rte_eth_dev *dev,
    4191                 :            :                            const struct rte_flow_item *item,
    4192                 :            :                            const struct rte_flow_attr *attr __rte_unused,
    4193                 :            :                            struct rte_flow_error *error)
    4194                 :            : {
    4195                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4196                 :          0 :         const struct rte_flow_item_meter_color *spec = item->spec;
    4197                 :          0 :         const struct rte_flow_item_meter_color *mask = item->mask;
    4198                 :          0 :         struct rte_flow_item_meter_color nic_mask = {
    4199                 :            :                 .color = RTE_COLORS
    4200                 :            :         };
    4201                 :            :         int ret;
    4202                 :            : 
    4203         [ #  # ]:          0 :         if (priv->sh->registers.aso_reg == REG_NON)
    4204                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4205                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    4206                 :            :                                           "meter color register"
    4207                 :            :                                           " isn't available");
    4208                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, error);
    4209         [ #  # ]:          0 :         if (ret < 0)
    4210                 :            :                 return ret;
    4211         [ #  # ]:          0 :         if (!spec)
    4212                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4213                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4214                 :          0 :                                           item->spec,
    4215                 :            :                                           "data cannot be empty");
    4216         [ #  # ]:          0 :         if (spec->color > RTE_COLORS)
    4217                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4218                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    4219                 :          0 :                                           &spec->color,
    4220                 :            :                                           "meter color is invalid");
    4221         [ #  # ]:          0 :         if (!mask)
    4222                 :            :                 mask = &rte_flow_item_meter_color_mask;
    4223         [ #  # ]:          0 :         if (!mask->color)
    4224                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4225                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    4226                 :            :                                         "mask cannot be zero");
    4227                 :            : 
    4228                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    4229                 :            :                                 (const uint8_t *)&nic_mask,
    4230                 :            :                                 sizeof(struct rte_flow_item_meter_color),
    4231                 :            :                                 MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    4232                 :            :         if (ret < 0)
    4233                 :            :                 return ret;
    4234                 :            :         return 0;
    4235                 :            : }
    4236                 :            : 
    4237                 :            : /**
    4238                 :            :  * Validate aggregated affinity item.
    4239                 :            :  *
    4240                 :            :  * @param[in] dev
    4241                 :            :  *   Pointer to the rte_eth_dev structure.
    4242                 :            :  * @param[in] item
    4243                 :            :  *   Item specification.
    4244                 :            :  * @param[in] attr
    4245                 :            :  *   Attributes of flow that includes this item.
    4246                 :            :  * @param[out] error
    4247                 :            :  *   Pointer to error structure.
    4248                 :            :  *
    4249                 :            :  * @return
    4250                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4251                 :            :  */
    4252                 :            : static int
    4253                 :          0 : flow_dv_validate_item_aggr_affinity(struct rte_eth_dev *dev,
    4254                 :            :                                    const struct rte_flow_item *item,
    4255                 :            :                                    const struct rte_flow_attr *attr,
    4256                 :            :                                    struct rte_flow_error *error)
    4257                 :            : {
    4258                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4259                 :          0 :         const struct rte_flow_item_aggr_affinity *spec = item->spec;
    4260                 :          0 :         const struct rte_flow_item_aggr_affinity *mask = item->mask;
    4261                 :          0 :         struct rte_flow_item_aggr_affinity nic_mask = {
    4262                 :            :                 .affinity = UINT8_MAX
    4263                 :            :         };
    4264                 :            :         int ret;
    4265                 :            : 
    4266         [ #  # ]:          0 :         if (!priv->sh->lag_rx_port_affinity_en)
    4267                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4268                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    4269                 :            :                                           "Unsupported aggregated affinity with Older FW");
    4270   [ #  #  #  #  :          0 :         if ((attr->transfer && priv->fdb_def_rule) ||
                   #  # ]
    4271         [ #  # ]:          0 :             attr->egress || attr->group)
    4272                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4273                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4274                 :            :                                           item->spec,
    4275                 :            :                                           "aggregated affinity is not supported with egress or FDB on non root table");
    4276         [ #  # ]:          0 :         if (!spec)
    4277                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4278                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4279                 :            :                                           item->spec,
    4280                 :            :                                           "data cannot be empty");
    4281         [ #  # ]:          0 :         if (spec->affinity == 0)
    4282                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4283                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4284                 :            :                                           item->spec,
    4285                 :            :                                           "zero affinity number not supported");
    4286         [ #  # ]:          0 :         if (spec->affinity > priv->num_lag_ports)
    4287                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4288                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4289                 :            :                                           item->spec,
    4290                 :            :                                           "exceed max affinity number in lag ports");
    4291         [ #  # ]:          0 :         if (!mask)
    4292                 :            :                 mask = &rte_flow_item_aggr_affinity_mask;
    4293         [ #  # ]:          0 :         if (!mask->affinity)
    4294                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4295                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    4296                 :            :                                           "mask cannot be zero");
    4297                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    4298                 :            :                                 (const uint8_t *)&nic_mask,
    4299                 :            :                                 sizeof(struct rte_flow_item_aggr_affinity),
    4300                 :            :                                 MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    4301                 :            :         if (ret < 0)
    4302                 :            :                 return ret;
    4303                 :            :         return 0;
    4304                 :            : }
    4305                 :            : 
    4306                 :            : int
    4307                 :          0 : flow_encap_decap_match_cb(void *tool_ctx __rte_unused,
    4308                 :            :                              struct mlx5_list_entry *entry, void *cb_ctx)
    4309                 :            : {
    4310                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4311                 :          0 :         struct mlx5_flow_dv_encap_decap_resource *ctx_resource = ctx->data;
    4312                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
    4313                 :            : 
    4314                 :            :         resource = container_of(entry, struct mlx5_flow_dv_encap_decap_resource,
    4315                 :            :                                 entry);
    4316         [ #  # ]:          0 :         if (resource->reformat_type == ctx_resource->reformat_type &&
    4317                 :          0 :             resource->ft_type == ctx_resource->ft_type &&
    4318         [ #  # ]:          0 :             resource->flags == ctx_resource->flags &&
    4319         [ #  # ]:          0 :             resource->size == ctx_resource->size &&
    4320                 :          0 :             !memcmp((const void *)resource->buf,
    4321         [ #  # ]:          0 :                     (const void *)ctx_resource->buf,
    4322                 :            :                     resource->size))
    4323                 :          0 :                 return 0;
    4324                 :            :         return -1;
    4325                 :            : }
    4326                 :            : 
    4327                 :            : struct mlx5_list_entry *
    4328                 :          0 : flow_encap_decap_create_cb(void *tool_ctx, void *cb_ctx)
    4329                 :            : {
    4330                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4331                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4332                 :            :         struct mlx5dv_dr_domain *domain;
    4333                 :          0 :         struct mlx5_flow_dv_encap_decap_resource *ctx_resource = ctx->data;
    4334                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
    4335                 :            :         uint32_t idx;
    4336                 :            :         int ret = 0;
    4337                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    4338                 :            :         struct mlx5dr_action_reformat_header hdr;
    4339                 :            : #endif
    4340                 :            : 
    4341                 :            :         /* Register new encap/decap resource. */
    4342                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], &idx);
    4343         [ #  # ]:          0 :         if (!resource) {
    4344                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4345                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4346                 :            :                                    "cannot allocate resource memory");
    4347                 :          0 :                 return NULL;
    4348                 :            :         }
    4349                 :          0 :         *resource = *ctx_resource;
    4350         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2) {
    4351                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    4352                 :          0 :                 hdr.sz = ctx_resource->size;
    4353                 :          0 :                 hdr.data = ctx_resource->buf;
    4354                 :          0 :                 resource->action = mlx5dr_action_create_reformat
    4355                 :          0 :                 (ctx->data2, (enum mlx5dr_action_type)ctx_resource->reformat_type, 1,
    4356                 :          0 :                         &hdr, 0, ctx_resource->flags);
    4357         [ #  # ]:          0 :                 if (!resource->action)
    4358                 :            :                         ret = -1;
    4359                 :            : #else
    4360                 :            :                 ret = -1;
    4361                 :            : #endif
    4362                 :            :         } else {
    4363         [ #  # ]:          0 :                 if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    4364                 :          0 :                         domain = sh->fdb_domain;
    4365         [ #  # ]:          0 :                 else if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
    4366                 :          0 :                         domain = sh->rx_domain;
    4367                 :            :                 else
    4368                 :          0 :                         domain = sh->tx_domain;
    4369         [ #  # ]:          0 :                 ret = mlx5_flow_os_create_flow_action_packet_reformat(sh->cdev->ctx,
    4370                 :            :                         domain, resource,
    4371                 :            :                 &resource->action);
    4372                 :            :         }
    4373                 :            :         if (ret) {
    4374                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], idx);
    4375                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4376                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4377                 :            :                                    NULL, "cannot create action");
    4378                 :          0 :                 return NULL;
    4379                 :            :         }
    4380                 :          0 :         resource->idx = idx;
    4381                 :          0 :         return &resource->entry;
    4382                 :            : }
    4383                 :            : 
    4384                 :            : struct mlx5_list_entry *
    4385                 :          0 : flow_encap_decap_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
    4386                 :            :                              void *cb_ctx)
    4387                 :            : {
    4388                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4389                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4390                 :            :         struct mlx5_flow_dv_encap_decap_resource *cache_resource;
    4391                 :            :         uint32_t idx;
    4392                 :            : 
    4393                 :          0 :         cache_resource = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
    4394                 :            :                                            &idx);
    4395         [ #  # ]:          0 :         if (!cache_resource) {
    4396                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4397                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4398                 :            :                                    "cannot allocate resource memory");
    4399                 :          0 :                 return NULL;
    4400                 :            :         }
    4401                 :            :         memcpy(cache_resource, oentry, sizeof(*cache_resource));
    4402                 :          0 :         cache_resource->idx = idx;
    4403                 :          0 :         return &cache_resource->entry;
    4404                 :            : }
    4405                 :            : 
    4406                 :            : void
    4407                 :          0 : flow_encap_decap_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4408                 :            : {
    4409                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4410                 :            :         struct mlx5_flow_dv_encap_decap_resource *res =
    4411                 :            :                                        container_of(entry, typeof(*res), entry);
    4412                 :            : 
    4413                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx);
    4414                 :          0 : }
    4415                 :            : 
    4416                 :            : int
    4417                 :          0 : __flow_encap_decap_resource_register(struct rte_eth_dev *dev,
    4418                 :            :                          struct mlx5_flow_dv_encap_decap_resource *resource,
    4419                 :            :                          bool is_root,
    4420                 :            :                          struct mlx5_flow_dv_encap_decap_resource **encap_decap,
    4421                 :            :                          struct rte_flow_error *error)
    4422                 :            : {
    4423                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4424                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
    4425                 :            :         struct mlx5_list_entry *entry;
    4426                 :            :         union {
    4427                 :            :                 struct {
    4428                 :            :                         uint32_t ft_type:8;
    4429                 :            :                         uint32_t refmt_type:8;
    4430                 :            :                         /*
    4431                 :            :                          * Header reformat actions can be shared between
    4432                 :            :                          * non-root tables. One bit to indicate non-root
    4433                 :            :                          * table or not.
    4434                 :            :                          */
    4435                 :            :                         uint32_t is_root:1;
    4436                 :            :                         uint32_t reserve:15;
    4437                 :            :                 };
    4438                 :            :                 uint32_t v32;
    4439                 :          0 :         } encap_decap_key = {
    4440                 :            :                 {
    4441                 :          0 :                         .ft_type = resource->ft_type,
    4442                 :          0 :                         .refmt_type = resource->reformat_type,
    4443                 :            :                         .is_root = is_root,
    4444                 :            :                         .reserve = 0,
    4445                 :            :                 }
    4446                 :            :         };
    4447                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4448                 :            :                 .error = error,
    4449                 :            :                 .data = resource,
    4450                 :          0 :                 .data2 = priv->dr_ctx,
    4451                 :            :         };
    4452                 :            :         struct mlx5_hlist *encaps_decaps;
    4453                 :            :         uint64_t key64;
    4454                 :            : 
    4455                 :          0 :         encaps_decaps = flow_dv_hlist_prepare(sh, &sh->encaps_decaps,
    4456                 :            :                                 "encaps_decaps",
    4457                 :            :                                 MLX5_FLOW_ENCAP_DECAP_HTABLE_SZ,
    4458                 :            :                                 true, true, sh,
    4459                 :            :                                 flow_encap_decap_create_cb,
    4460                 :            :                                 flow_encap_decap_match_cb,
    4461                 :            :                                 flow_encap_decap_remove_cb,
    4462                 :            :                                 flow_encap_decap_clone_cb,
    4463                 :            :                                 flow_encap_decap_clone_free_cb,
    4464                 :            :                                 error);
    4465         [ #  # ]:          0 :         if (unlikely(!encaps_decaps))
    4466                 :          0 :                 return -rte_errno;
    4467                 :          0 :         key64 =  __rte_raw_cksum(&encap_decap_key.v32,
    4468                 :            :                                  sizeof(encap_decap_key.v32), 0);
    4469         [ #  # ]:          0 :         if (resource->reformat_type !=
    4470                 :          0 :             MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2 &&
    4471         [ #  # ]:          0 :             resource->size)
    4472                 :          0 :                 key64 = __rte_raw_cksum(resource->buf, resource->size, key64);
    4473                 :          0 :         entry = mlx5_hlist_register(encaps_decaps, key64, &ctx);
    4474         [ #  # ]:          0 :         if (!entry)
    4475                 :          0 :                 return -rte_errno;
    4476                 :          0 :         *encap_decap = container_of(entry, typeof(*resource), entry);
    4477                 :          0 :         return 0;
    4478                 :            : }
    4479                 :            : 
    4480                 :            : /**
    4481                 :            :  * Find existing encap/decap resource or create and register a new one.
    4482                 :            :  *
    4483                 :            :  * @param[in, out] dev
    4484                 :            :  *   Pointer to rte_eth_dev structure.
    4485                 :            :  * @param[in, out] resource
    4486                 :            :  *   Pointer to encap/decap resource.
    4487                 :            :  * @param[in, out] dev_flow
    4488                 :            :  *   Pointer to the dev_flow.
    4489                 :            :  * @param[out] error
    4490                 :            :  *   pointer to error structure.
    4491                 :            :  *
    4492                 :            :  * @return
    4493                 :            :  *   0 on success otherwise -errno and errno is set.
    4494                 :            :  */
    4495                 :            : static int
    4496                 :          0 : flow_dv_encap_decap_resource_register
    4497                 :            :                         (struct rte_eth_dev *dev,
    4498                 :            :                          struct mlx5_flow_dv_encap_decap_resource *resource,
    4499                 :            :                          struct mlx5_flow *dev_flow,
    4500                 :            :                          struct rte_flow_error *error)
    4501                 :            : {
    4502                 :            :         int ret;
    4503                 :            : 
    4504                 :          0 :         resource->flags = dev_flow->dv.group ? 0 : 1;
    4505                 :          0 :         ret = __flow_encap_decap_resource_register(dev, resource, !!dev_flow->dv.group,
    4506                 :            :                 &dev_flow->dv.encap_decap, error);
    4507         [ #  # ]:          0 :         if (ret)
    4508                 :            :                 return ret;
    4509                 :          0 :         dev_flow->handle->dvh.rix_encap_decap = dev_flow->dv.encap_decap->idx;
    4510                 :          0 :         return 0;
    4511                 :            : }
    4512                 :            : 
    4513                 :            : /**
    4514                 :            :  * Find existing table jump resource or create and register a new one.
    4515                 :            :  *
    4516                 :            :  * @param[in, out] dev
    4517                 :            :  *   Pointer to rte_eth_dev structure.
    4518                 :            :  * @param[in, out] tbl
    4519                 :            :  *   Pointer to flow table resource.
    4520                 :            :  * @parm[in, out] dev_flow
    4521                 :            :  *   Pointer to the dev_flow.
    4522                 :            :  * @param[out] error
    4523                 :            :  *   pointer to error structure.
    4524                 :            :  *
    4525                 :            :  * @return
    4526                 :            :  *   0 on success otherwise -errno and errno is set.
    4527                 :            :  */
    4528                 :            : static int
    4529                 :            : flow_dv_jump_tbl_resource_register
    4530                 :            :                         (struct rte_eth_dev *dev __rte_unused,
    4531                 :            :                          struct mlx5_flow_tbl_resource *tbl,
    4532                 :            :                          struct mlx5_flow *dev_flow,
    4533                 :            :                          struct rte_flow_error *error __rte_unused)
    4534                 :            : {
    4535                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
    4536                 :          0 :                 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
    4537                 :            : 
    4538                 :            :         MLX5_ASSERT(tbl);
    4539                 :            :         MLX5_ASSERT(tbl_data->jump.action);
    4540                 :          0 :         dev_flow->handle->rix_jump = tbl_data->idx;
    4541                 :          0 :         dev_flow->dv.jump = &tbl_data->jump;
    4542                 :            :         return 0;
    4543                 :            : }
    4544                 :            : 
    4545                 :            : int
    4546                 :          0 : flow_dv_port_id_match_cb(void *tool_ctx __rte_unused,
    4547                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
    4548                 :            : {
    4549                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4550                 :          0 :         struct mlx5_flow_dv_port_id_action_resource *ref = ctx->data;
    4551                 :            :         struct mlx5_flow_dv_port_id_action_resource *res =
    4552                 :            :                                        container_of(entry, typeof(*res), entry);
    4553                 :            : 
    4554                 :          0 :         return ref->port_id != res->port_id;
    4555                 :            : }
    4556                 :            : 
    4557                 :            : struct mlx5_list_entry *
    4558                 :          0 : flow_dv_port_id_create_cb(void *tool_ctx, void *cb_ctx)
    4559                 :            : {
    4560                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4561                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4562                 :          0 :         struct mlx5_flow_dv_port_id_action_resource *ref = ctx->data;
    4563                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4564                 :            :         uint32_t idx;
    4565                 :            :         int ret;
    4566                 :            : 
    4567                 :            :         /* Register new port id action resource. */
    4568                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID], &idx);
    4569         [ #  # ]:          0 :         if (!resource) {
    4570                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4571                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4572                 :            :                                    "cannot allocate port_id action memory");
    4573                 :          0 :                 return NULL;
    4574                 :            :         }
    4575                 :          0 :         *resource = *ref;
    4576                 :          0 :         ret = mlx5_flow_os_create_flow_action_dest_port(sh->fdb_domain,
    4577                 :            :                                                         ref->port_id,
    4578                 :            :                                                         &resource->action);
    4579                 :            :         if (ret) {
    4580                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], idx);
    4581                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4582                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4583                 :            :                                    "cannot create action");
    4584                 :          0 :                 return NULL;
    4585                 :            :         }
    4586                 :          0 :         resource->idx = idx;
    4587                 :          0 :         return &resource->entry;
    4588                 :            : }
    4589                 :            : 
    4590                 :            : struct mlx5_list_entry *
    4591                 :          0 : flow_dv_port_id_clone_cb(void *tool_ctx,
    4592                 :            :                          struct mlx5_list_entry *entry __rte_unused,
    4593                 :            :                          void *cb_ctx)
    4594                 :            : {
    4595                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4596                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4597                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4598                 :            :         uint32_t idx;
    4599                 :            : 
    4600                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID], &idx);
    4601         [ #  # ]:          0 :         if (!resource) {
    4602                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4603                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4604                 :            :                                    "cannot allocate port_id action memory");
    4605                 :          0 :                 return NULL;
    4606                 :            :         }
    4607                 :            :         memcpy(resource, entry, sizeof(*resource));
    4608                 :          0 :         resource->idx = idx;
    4609                 :          0 :         return &resource->entry;
    4610                 :            : }
    4611                 :            : 
    4612                 :            : void
    4613                 :          0 : flow_dv_port_id_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4614                 :            : {
    4615                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4616                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource =
    4617                 :            :                                   container_of(entry, typeof(*resource), entry);
    4618                 :            : 
    4619                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], resource->idx);
    4620                 :          0 : }
    4621                 :            : 
    4622                 :            : /**
    4623                 :            :  * Find existing table port ID resource or create and register a new one.
    4624                 :            :  *
    4625                 :            :  * @param[in, out] dev
    4626                 :            :  *   Pointer to rte_eth_dev structure.
    4627                 :            :  * @param[in, out] ref
    4628                 :            :  *   Pointer to port ID action resource reference.
    4629                 :            :  * @parm[in, out] dev_flow
    4630                 :            :  *   Pointer to the dev_flow.
    4631                 :            :  * @param[out] error
    4632                 :            :  *   pointer to error structure.
    4633                 :            :  *
    4634                 :            :  * @return
    4635                 :            :  *   0 on success otherwise -errno and errno is set.
    4636                 :            :  */
    4637                 :            : static int
    4638                 :          0 : flow_dv_port_id_action_resource_register
    4639                 :            :                         (struct rte_eth_dev *dev,
    4640                 :            :                          struct mlx5_flow_dv_port_id_action_resource *ref,
    4641                 :            :                          struct mlx5_flow *dev_flow,
    4642                 :            :                          struct rte_flow_error *error)
    4643                 :            : {
    4644                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4645                 :            :         struct mlx5_list_entry *entry;
    4646                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4647                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4648                 :            :                 .error = error,
    4649                 :            :                 .data = ref,
    4650                 :            :         };
    4651                 :            : 
    4652                 :          0 :         entry = mlx5_list_register(priv->sh->port_id_action_list, &ctx);
    4653         [ #  # ]:          0 :         if (!entry)
    4654                 :          0 :                 return -rte_errno;
    4655                 :            :         resource = container_of(entry, typeof(*resource), entry);
    4656                 :          0 :         dev_flow->dv.port_id_action = resource;
    4657                 :          0 :         dev_flow->handle->rix_port_id_action = resource->idx;
    4658                 :          0 :         return 0;
    4659                 :            : }
    4660                 :            : 
    4661                 :            : int
    4662                 :          0 : flow_dv_push_vlan_match_cb(void *tool_ctx __rte_unused,
    4663                 :            :                            struct mlx5_list_entry *entry, void *cb_ctx)
    4664                 :            : {
    4665                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4666                 :          0 :         struct mlx5_flow_dv_push_vlan_action_resource *ref = ctx->data;
    4667                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *res =
    4668                 :            :                                        container_of(entry, typeof(*res), entry);
    4669                 :            : 
    4670                 :          0 :         return ref->vlan_tag != res->vlan_tag || ref->ft_type != res->ft_type;
    4671                 :            : }
    4672                 :            : 
    4673                 :            : struct mlx5_list_entry *
    4674                 :          0 : flow_dv_push_vlan_create_cb(void *tool_ctx, void *cb_ctx)
    4675                 :            : {
    4676                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4677                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4678                 :          0 :         struct mlx5_flow_dv_push_vlan_action_resource *ref = ctx->data;
    4679                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4680                 :            :         struct mlx5dv_dr_domain *domain;
    4681                 :            :         uint32_t idx;
    4682                 :            :         int ret;
    4683                 :            : 
    4684                 :            :         /* Register new port id action resource. */
    4685                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PUSH_VLAN], &idx);
    4686         [ #  # ]:          0 :         if (!resource) {
    4687                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4688                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4689                 :            :                                    "cannot allocate push_vlan action memory");
    4690                 :          0 :                 return NULL;
    4691                 :            :         }
    4692                 :          0 :         *resource = *ref;
    4693         [ #  # ]:          0 :         if (ref->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    4694                 :          0 :                 domain = sh->fdb_domain;
    4695         [ #  # ]:          0 :         else if (ref->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
    4696                 :          0 :                 domain = sh->rx_domain;
    4697                 :            :         else
    4698                 :          0 :                 domain = sh->tx_domain;
    4699                 :          0 :         ret = mlx5_flow_os_create_flow_action_push_vlan(domain, ref->vlan_tag,
    4700                 :            :                                                         &resource->action);
    4701                 :            :         if (ret) {
    4702                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx);
    4703                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4704                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4705                 :            :                                    "cannot create push vlan action");
    4706                 :          0 :                 return NULL;
    4707                 :            :         }
    4708                 :          0 :         resource->idx = idx;
    4709                 :          0 :         return &resource->entry;
    4710                 :            : }
    4711                 :            : 
    4712                 :            : struct mlx5_list_entry *
    4713                 :          0 : flow_dv_push_vlan_clone_cb(void *tool_ctx,
    4714                 :            :                            struct mlx5_list_entry *entry __rte_unused,
    4715                 :            :                            void *cb_ctx)
    4716                 :            : {
    4717                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4718                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4719                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4720                 :            :         uint32_t idx;
    4721                 :            : 
    4722                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PUSH_VLAN], &idx);
    4723         [ #  # ]:          0 :         if (!resource) {
    4724                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4725                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4726                 :            :                                    "cannot allocate push_vlan action memory");
    4727                 :          0 :                 return NULL;
    4728                 :            :         }
    4729                 :            :         memcpy(resource, entry, sizeof(*resource));
    4730                 :          0 :         resource->idx = idx;
    4731                 :          0 :         return &resource->entry;
    4732                 :            : }
    4733                 :            : 
    4734                 :            : void
    4735                 :          0 : flow_dv_push_vlan_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4736                 :            : {
    4737                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4738                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource =
    4739                 :            :                                   container_of(entry, typeof(*resource), entry);
    4740                 :            : 
    4741                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], resource->idx);
    4742                 :          0 : }
    4743                 :            : 
    4744                 :            : /**
    4745                 :            :  * Find existing push vlan resource or create and register a new one.
    4746                 :            :  *
    4747                 :            :  * @param [in, out] dev
    4748                 :            :  *   Pointer to rte_eth_dev structure.
    4749                 :            :  * @param[in, out] ref
    4750                 :            :  *   Pointer to port ID action resource reference.
    4751                 :            :  * @parm[in, out] dev_flow
    4752                 :            :  *   Pointer to the dev_flow.
    4753                 :            :  * @param[out] error
    4754                 :            :  *   pointer to error structure.
    4755                 :            :  *
    4756                 :            :  * @return
    4757                 :            :  *   0 on success otherwise -errno and errno is set.
    4758                 :            :  */
    4759                 :            : static int
    4760                 :          0 : flow_dv_push_vlan_action_resource_register
    4761                 :            :                        (struct rte_eth_dev *dev,
    4762                 :            :                         struct mlx5_flow_dv_push_vlan_action_resource *ref,
    4763                 :            :                         struct mlx5_flow *dev_flow,
    4764                 :            :                         struct rte_flow_error *error)
    4765                 :            : {
    4766                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4767                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4768                 :            :         struct mlx5_list_entry *entry;
    4769                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4770                 :            :                 .error = error,
    4771                 :            :                 .data = ref,
    4772                 :            :         };
    4773                 :            : 
    4774                 :          0 :         entry = mlx5_list_register(priv->sh->push_vlan_action_list, &ctx);
    4775         [ #  # ]:          0 :         if (!entry)
    4776                 :          0 :                 return -rte_errno;
    4777                 :            :         resource = container_of(entry, typeof(*resource), entry);
    4778                 :            : 
    4779                 :          0 :         dev_flow->handle->dvh.rix_push_vlan = resource->idx;
    4780                 :          0 :         dev_flow->dv.push_vlan_res = resource;
    4781                 :          0 :         return 0;
    4782                 :            : }
    4783                 :            : 
    4784                 :            : /**
    4785                 :            :  * Get the size of specific rte_flow_item_type hdr size
    4786                 :            :  *
    4787                 :            :  * @param[in] item_type
    4788                 :            :  *   Tested rte_flow_item_type.
    4789                 :            :  *
    4790                 :            :  * @return
    4791                 :            :  *   sizeof struct item_type, 0 if void or irrelevant.
    4792                 :            :  */
    4793                 :            : size_t
    4794         [ #  # ]:          0 : flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type)
    4795                 :            : {
    4796                 :            :         size_t retval;
    4797                 :            : 
    4798                 :            :         switch (item_type) {
    4799                 :            :         case RTE_FLOW_ITEM_TYPE_ETH:
    4800                 :            :                 retval = sizeof(struct rte_ether_hdr);
    4801                 :            :                 break;
    4802                 :            :         case RTE_FLOW_ITEM_TYPE_VLAN:
    4803                 :            :                 retval = sizeof(struct rte_vlan_hdr);
    4804                 :            :                 break;
    4805                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:
    4806                 :            :                 retval = sizeof(struct rte_ipv4_hdr);
    4807                 :            :                 break;
    4808                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:
    4809                 :            :                 retval = sizeof(struct rte_ipv6_hdr);
    4810                 :            :                 break;
    4811                 :            :         case RTE_FLOW_ITEM_TYPE_UDP:
    4812                 :            :                 retval = sizeof(struct rte_udp_hdr);
    4813                 :            :                 break;
    4814                 :            :         case RTE_FLOW_ITEM_TYPE_TCP:
    4815                 :            :                 retval = sizeof(struct rte_tcp_hdr);
    4816                 :            :                 break;
    4817                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN:
    4818                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    4819                 :            :                 retval = sizeof(struct rte_vxlan_hdr);
    4820                 :            :                 break;
    4821                 :            :         case RTE_FLOW_ITEM_TYPE_GRE:
    4822                 :            :         case RTE_FLOW_ITEM_TYPE_NVGRE:
    4823                 :            :                 retval = sizeof(struct rte_gre_hdr);
    4824                 :            :                 break;
    4825                 :            :         case RTE_FLOW_ITEM_TYPE_MPLS:
    4826                 :            :                 retval = sizeof(struct rte_mpls_hdr);
    4827                 :            :                 break;
    4828                 :            :         case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
    4829                 :            :         default:
    4830                 :            :                 retval = 0;
    4831                 :            :                 break;
    4832                 :            :         }
    4833                 :          0 :         return retval;
    4834                 :            : }
    4835                 :            : 
    4836                 :            : #define MLX5_ENCAP_IPV4_VERSION         0x40
    4837                 :            : #define MLX5_ENCAP_IPV4_IHL_MIN         0x05
    4838                 :            : #define MLX5_ENCAP_IPV4_TTL_DEF         0x40
    4839                 :            : #define MLX5_ENCAP_IPV6_VTC_FLOW        0x60000000
    4840                 :            : #define MLX5_ENCAP_IPV6_HOP_LIMIT       0xff
    4841                 :            : #define MLX5_ENCAP_VXLAN_FLAGS          0x08000000
    4842                 :            : #define MLX5_ENCAP_VXLAN_GPE_FLAGS      0x04
    4843                 :            : 
    4844                 :            : /**
    4845                 :            :  * Convert the encap action data from list of rte_flow_item to raw buffer
    4846                 :            :  *
    4847                 :            :  * @param[in] items
    4848                 :            :  *   Pointer to rte_flow_item objects list.
    4849                 :            :  * @param[out] buf
    4850                 :            :  *   Pointer to the output buffer.
    4851                 :            :  * @param[out] size
    4852                 :            :  *   Pointer to the output buffer size.
    4853                 :            :  * @param[out] error
    4854                 :            :  *   Pointer to the error structure.
    4855                 :            :  *
    4856                 :            :  * @return
    4857                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4858                 :            :  */
    4859                 :            : int
    4860                 :          0 : flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
    4861                 :            :                            size_t *size, struct rte_flow_error *error)
    4862                 :            : {
    4863                 :            :         struct rte_ether_hdr *eth = NULL;
    4864                 :            :         struct rte_vlan_hdr *vlan = NULL;
    4865                 :            :         struct rte_ipv4_hdr *ipv4 = NULL;
    4866                 :            :         struct rte_ipv6_hdr *ipv6 = NULL;
    4867                 :            :         struct rte_udp_hdr *udp = NULL;
    4868                 :            :         struct rte_vxlan_hdr *vxlan = NULL;
    4869                 :            :         struct rte_vxlan_gpe_hdr *vxlan_gpe = NULL;
    4870                 :            :         struct rte_gre_hdr *gre = NULL;
    4871                 :            :         size_t len;
    4872                 :            :         size_t temp_size = 0;
    4873                 :            : 
    4874         [ #  # ]:          0 :         if (!items)
    4875                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4876                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    4877                 :            :                                           NULL, "invalid empty data");
    4878         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    4879                 :          0 :                 len = flow_dv_get_item_hdr_len(items->type);
    4880         [ #  # ]:          0 :                 if (len + temp_size > MLX5_ENCAP_MAX_LEN)
    4881                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4882                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4883                 :          0 :                                                   (void *)items->type,
    4884                 :            :                                                   "items total size is too big"
    4885                 :            :                                                   " for encap action");
    4886         [ #  # ]:          0 :                 if (items->spec)
    4887         [ #  # ]:          0 :                         rte_memcpy(&buf[temp_size], items->spec, len);
    4888   [ #  #  #  #  :          0 :                 switch (items->type) {
          #  #  #  #  #  
                      # ]
    4889                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    4890                 :          0 :                         eth = (struct rte_ether_hdr *)&buf[temp_size];
    4891                 :          0 :                         break;
    4892                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    4893                 :          0 :                         vlan = (struct rte_vlan_hdr *)&buf[temp_size];
    4894         [ #  # ]:          0 :                         if (!eth)
    4895                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4896                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4897                 :            :                                                 (void *)items->type,
    4898                 :            :                                                 "eth header not found");
    4899         [ #  # ]:          0 :                         if (!eth->ether_type)
    4900                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_VLAN);
    4901                 :            :                         break;
    4902                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    4903                 :          0 :                         ipv4 = (struct rte_ipv4_hdr *)&buf[temp_size];
    4904         [ #  # ]:          0 :                         if (!vlan && !eth)
    4905                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4906                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4907                 :            :                                                 (void *)items->type,
    4908                 :            :                                                 "neither eth nor vlan"
    4909                 :            :                                                 " header found");
    4910   [ #  #  #  # ]:          0 :                         if (vlan && !vlan->eth_proto)
    4911                 :          0 :                                 vlan->eth_proto = RTE_BE16(RTE_ETHER_TYPE_IPV4);
    4912   [ #  #  #  # ]:          0 :                         else if (eth && !eth->ether_type)
    4913                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV4);
    4914         [ #  # ]:          0 :                         if (!ipv4->version_ihl)
    4915                 :          0 :                                 ipv4->version_ihl = MLX5_ENCAP_IPV4_VERSION |
    4916                 :            :                                                     MLX5_ENCAP_IPV4_IHL_MIN;
    4917         [ #  # ]:          0 :                         if (!ipv4->time_to_live)
    4918                 :          0 :                                 ipv4->time_to_live = MLX5_ENCAP_IPV4_TTL_DEF;
    4919                 :            :                         break;
    4920                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    4921                 :          0 :                         ipv6 = (struct rte_ipv6_hdr *)&buf[temp_size];
    4922         [ #  # ]:          0 :                         if (!vlan && !eth)
    4923                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4924                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4925                 :            :                                                 (void *)items->type,
    4926                 :            :                                                 "neither eth nor vlan"
    4927                 :            :                                                 " header found");
    4928   [ #  #  #  # ]:          0 :                         if (vlan && !vlan->eth_proto)
    4929                 :          0 :                                 vlan->eth_proto = RTE_BE16(RTE_ETHER_TYPE_IPV6);
    4930   [ #  #  #  # ]:          0 :                         else if (eth && !eth->ether_type)
    4931                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
    4932         [ #  # ]:          0 :                         if (!ipv6->vtc_flow)
    4933                 :          0 :                                 ipv6->vtc_flow =
    4934                 :            :                                         RTE_BE32(MLX5_ENCAP_IPV6_VTC_FLOW);
    4935         [ #  # ]:          0 :                         if (!ipv6->hop_limits)
    4936                 :          0 :                                 ipv6->hop_limits = MLX5_ENCAP_IPV6_HOP_LIMIT;
    4937                 :            :                         break;
    4938                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    4939                 :          0 :                         udp = (struct rte_udp_hdr *)&buf[temp_size];
    4940         [ #  # ]:          0 :                         if (!ipv4 && !ipv6)
    4941                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4942                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4943                 :            :                                                 (void *)items->type,
    4944                 :            :                                                 "ip header not found");
    4945   [ #  #  #  # ]:          0 :                         if (ipv4 && !ipv4->next_proto_id)
    4946                 :          0 :                                 ipv4->next_proto_id = IPPROTO_UDP;
    4947   [ #  #  #  # ]:          0 :                         else if (ipv6 && !ipv6->proto)
    4948                 :          0 :                                 ipv6->proto = IPPROTO_UDP;
    4949                 :            :                         break;
    4950                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    4951                 :          0 :                         vxlan = (struct rte_vxlan_hdr *)&buf[temp_size];
    4952         [ #  # ]:          0 :                         if (!udp)
    4953                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4954                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4955                 :            :                                                 (void *)items->type,
    4956                 :            :                                                 "udp header not found");
    4957         [ #  # ]:          0 :                         if (!udp->dst_port)
    4958                 :          0 :                                 udp->dst_port = RTE_BE16(MLX5_UDP_PORT_VXLAN);
    4959         [ #  # ]:          0 :                         if (!vxlan->vx_flags)
    4960                 :          0 :                                 vxlan->vx_flags =
    4961                 :            :                                         RTE_BE32(MLX5_ENCAP_VXLAN_FLAGS);
    4962                 :            :                         break;
    4963                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    4964                 :          0 :                         vxlan_gpe = (struct rte_vxlan_gpe_hdr *)&buf[temp_size];
    4965         [ #  # ]:          0 :                         if (!udp)
    4966                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4967                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4968                 :            :                                                 (void *)items->type,
    4969                 :            :                                                 "udp header not found");
    4970         [ #  # ]:          0 :                         if (!vxlan_gpe->proto)
    4971                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4972                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4973                 :            :                                                 (void *)items->type,
    4974                 :            :                                                 "next protocol not found");
    4975         [ #  # ]:          0 :                         if (!udp->dst_port)
    4976                 :          0 :                                 udp->dst_port =
    4977                 :            :                                         RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
    4978         [ #  # ]:          0 :                         if (!vxlan_gpe->vx_flags)
    4979                 :          0 :                                 vxlan_gpe->vx_flags =
    4980                 :            :                                                 MLX5_ENCAP_VXLAN_GPE_FLAGS;
    4981                 :            :                         break;
    4982                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
    4983                 :            :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    4984                 :          0 :                         gre = (struct rte_gre_hdr *)&buf[temp_size];
    4985         [ #  # ]:          0 :                         if (!gre->proto)
    4986                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4987                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4988                 :          0 :                                                 (void *)items->type,
    4989                 :            :                                                 "next protocol not found");
    4990         [ #  # ]:          0 :                         if (!ipv4 && !ipv6)
    4991                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4992                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4993                 :          0 :                                                 (void *)items->type,
    4994                 :            :                                                 "ip header not found");
    4995   [ #  #  #  # ]:          0 :                         if (ipv4 && !ipv4->next_proto_id)
    4996                 :          0 :                                 ipv4->next_proto_id = IPPROTO_GRE;
    4997   [ #  #  #  # ]:          0 :                         else if (ipv6 && !ipv6->proto)
    4998                 :          0 :                                 ipv6->proto = IPPROTO_GRE;
    4999                 :            :                         break;
    5000                 :            :                 case RTE_FLOW_ITEM_TYPE_VOID:
    5001                 :            :                         break;
    5002                 :          0 :                 default:
    5003                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5004                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5005                 :          0 :                                                   (void *)items->type,
    5006                 :            :                                                   "unsupported item type");
    5007                 :            :                         break;
    5008                 :            :                 }
    5009                 :            :                 temp_size += len;
    5010                 :            :         }
    5011                 :          0 :         *size = temp_size;
    5012                 :          0 :         return 0;
    5013                 :            : }
    5014                 :            : 
    5015                 :            : static int
    5016                 :          0 : flow_dv_zero_encap_udp_csum(void *data, struct rte_flow_error *error)
    5017                 :            : {
    5018                 :            :         struct rte_ether_hdr *eth = NULL;
    5019                 :            :         struct rte_vlan_hdr *vlan = NULL;
    5020                 :            :         struct rte_ipv4_hdr *ipv4 = NULL;
    5021                 :            :         struct rte_ipv6_hdr *ipv6 = NULL;
    5022                 :            :         struct rte_udp_hdr *udp = NULL;
    5023                 :            :         char *next_hdr;
    5024                 :            :         uint16_t proto;
    5025                 :            : 
    5026                 :            :         eth = (struct rte_ether_hdr *)data;
    5027                 :          0 :         next_hdr = (char *)(eth + 1);
    5028                 :          0 :         proto = RTE_BE16(eth->ether_type);
    5029                 :            : 
    5030                 :            :         /* VLAN skipping */
    5031         [ #  # ]:          0 :         while (proto == RTE_ETHER_TYPE_VLAN || proto == RTE_ETHER_TYPE_QINQ) {
    5032                 :            :                 vlan = (struct rte_vlan_hdr *)next_hdr;
    5033                 :          0 :                 proto = RTE_BE16(vlan->eth_proto);
    5034                 :          0 :                 next_hdr += sizeof(struct rte_vlan_hdr);
    5035                 :            :         }
    5036                 :            : 
    5037                 :            :         /* non IPv4/IPv6 header. not supported */
    5038         [ #  # ]:          0 :         if (proto != RTE_ETHER_TYPE_IPV4 && proto != RTE_ETHER_TYPE_IPV6) {
    5039                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5040                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5041                 :            :                                           NULL, "Cannot offload non IPv4/IPv6");
    5042                 :            :         }
    5043                 :            : 
    5044         [ #  # ]:          0 :         if (proto == RTE_ETHER_TYPE_IPV4) {
    5045                 :            :                 ipv4 = (struct rte_ipv4_hdr *)next_hdr;
    5046                 :            :                 /* ignore non UDP */
    5047         [ #  # ]:          0 :                 if (ipv4->next_proto_id != IPPROTO_UDP)
    5048                 :            :                         return 0;
    5049                 :          0 :                 udp = (struct rte_udp_hdr *)(ipv4 + 1);
    5050                 :            :         } else {
    5051                 :            :                 ipv6 = (struct rte_ipv6_hdr *)next_hdr;
    5052                 :            :                 /* ignore non UDP */
    5053         [ #  # ]:          0 :                 if (ipv6->proto != IPPROTO_UDP)
    5054                 :            :                         return 0;
    5055                 :          0 :                 udp = (struct rte_udp_hdr *)(ipv6 + 1);
    5056                 :            :         }
    5057                 :            : 
    5058                 :          0 :         udp->dgram_cksum = 0;
    5059                 :            : 
    5060                 :          0 :         return 0;
    5061                 :            : }
    5062                 :            : 
    5063                 :            : /**
    5064                 :            :  * Convert L2 encap action to DV specification.
    5065                 :            :  *
    5066                 :            :  * @param[in] dev
    5067                 :            :  *   Pointer to rte_eth_dev structure.
    5068                 :            :  * @param[in] action
    5069                 :            :  *   Pointer to action structure.
    5070                 :            :  * @param[in, out] dev_flow
    5071                 :            :  *   Pointer to the mlx5_flow.
    5072                 :            :  * @param[in] transfer
    5073                 :            :  *   Mark if the flow is E-Switch flow.
    5074                 :            :  * @param[out] error
    5075                 :            :  *   Pointer to the error structure.
    5076                 :            :  *
    5077                 :            :  * @return
    5078                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5079                 :            :  */
    5080                 :            : static int
    5081                 :          0 : flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
    5082                 :            :                                const struct rte_flow_action *action,
    5083                 :            :                                struct mlx5_flow *dev_flow,
    5084                 :            :                                uint8_t transfer,
    5085                 :            :                                struct rte_flow_error *error)
    5086                 :            : {
    5087                 :            :         const struct rte_flow_item *encap_data;
    5088                 :            :         const struct rte_flow_action_raw_encap *raw_encap_data;
    5089         [ #  # ]:          0 :         struct mlx5_flow_dv_encap_decap_resource res = {
    5090                 :            :                 .reformat_type =
    5091                 :            :                         MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
    5092                 :            :                 .ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
    5093                 :            :                                       MLX5DV_FLOW_TABLE_TYPE_NIC_TX,
    5094                 :            :         };
    5095                 :            : 
    5096         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    5097                 :          0 :                 raw_encap_data =
    5098                 :            :                         (const struct rte_flow_action_raw_encap *)action->conf;
    5099                 :          0 :                 res.size = raw_encap_data->size;
    5100                 :          0 :                 memcpy(res.buf, raw_encap_data->data, res.size);
    5101                 :            :         } else {
    5102         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
    5103                 :          0 :                         encap_data =
    5104                 :            :                                 ((const struct rte_flow_action_vxlan_encap *)
    5105                 :          0 :                                                 action->conf)->definition;
    5106                 :            :                 else
    5107                 :          0 :                         encap_data =
    5108                 :            :                                 ((const struct rte_flow_action_nvgre_encap *)
    5109                 :          0 :                                                 action->conf)->definition;
    5110         [ #  # ]:          0 :                 if (flow_dv_convert_encap_data(encap_data, res.buf,
    5111                 :            :                                                &res.size, error))
    5112                 :          0 :                         return -rte_errno;
    5113                 :            :         }
    5114         [ #  # ]:          0 :         if (flow_dv_zero_encap_udp_csum(res.buf, error))
    5115                 :          0 :                 return -rte_errno;
    5116         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5117                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5118                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5119                 :            :                                           NULL, "can't create L2 encap action");
    5120                 :            :         return 0;
    5121                 :            : }
    5122                 :            : 
    5123                 :            : /**
    5124                 :            :  * Convert L2 decap action to DV specification.
    5125                 :            :  *
    5126                 :            :  * @param[in] dev
    5127                 :            :  *   Pointer to rte_eth_dev structure.
    5128                 :            :  * @param[in, out] dev_flow
    5129                 :            :  *   Pointer to the mlx5_flow.
    5130                 :            :  * @param[in] transfer
    5131                 :            :  *   Mark if the flow is E-Switch flow.
    5132                 :            :  * @param[out] error
    5133                 :            :  *   Pointer to the error structure.
    5134                 :            :  *
    5135                 :            :  * @return
    5136                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5137                 :            :  */
    5138                 :            : static int
    5139                 :          0 : flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
    5140                 :            :                                struct mlx5_flow *dev_flow,
    5141                 :            :                                uint8_t transfer,
    5142                 :            :                                struct rte_flow_error *error)
    5143                 :            : {
    5144         [ #  # ]:          0 :         struct mlx5_flow_dv_encap_decap_resource res = {
    5145                 :            :                 .size = 0,
    5146                 :            :                 .reformat_type =
    5147                 :            :                         MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
    5148                 :            :                 .ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
    5149                 :            :                                       MLX5DV_FLOW_TABLE_TYPE_NIC_RX,
    5150                 :            :         };
    5151                 :            : 
    5152         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5153                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5154                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5155                 :            :                                           NULL, "can't create L2 decap action");
    5156                 :            :         return 0;
    5157                 :            : }
    5158                 :            : 
    5159                 :            : /**
    5160                 :            :  * Convert raw decap/encap (L3 tunnel) action to DV specification.
    5161                 :            :  *
    5162                 :            :  * @param[in] dev
    5163                 :            :  *   Pointer to rte_eth_dev structure.
    5164                 :            :  * @param[in] action
    5165                 :            :  *   Pointer to action structure.
    5166                 :            :  * @param[in, out] dev_flow
    5167                 :            :  *   Pointer to the mlx5_flow.
    5168                 :            :  * @param[in] attr
    5169                 :            :  *   Pointer to the flow attributes.
    5170                 :            :  * @param[out] error
    5171                 :            :  *   Pointer to the error structure.
    5172                 :            :  *
    5173                 :            :  * @return
    5174                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5175                 :            :  */
    5176                 :            : static int
    5177         [ #  # ]:          0 : flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
    5178                 :            :                                 const struct rte_flow_action *action,
    5179                 :            :                                 struct mlx5_flow *dev_flow,
    5180                 :            :                                 const struct rte_flow_attr *attr,
    5181                 :            :                                 struct rte_flow_error *error)
    5182                 :            : {
    5183                 :            :         const struct rte_flow_action_raw_encap *encap_data;
    5184                 :            :         struct mlx5_flow_dv_encap_decap_resource res;
    5185                 :            : 
    5186                 :            :         memset(&res, 0, sizeof(res));
    5187                 :          0 :         encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
    5188                 :          0 :         res.size = encap_data->size;
    5189         [ #  # ]:          0 :         memcpy(res.buf, encap_data->data, res.size);
    5190         [ #  # ]:          0 :         res.reformat_type = res.size < MLX5_ENCAPSULATION_DECISION_SIZE ?
    5191                 :            :                 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 :
    5192                 :            :                 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
    5193         [ #  # ]:          0 :         if (attr->transfer)
    5194                 :          0 :                 res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
    5195                 :            :         else
    5196                 :          0 :                 res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
    5197                 :            :                                              MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
    5198         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5199                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5200                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5201                 :            :                                           NULL, "can't create encap action");
    5202                 :            :         return 0;
    5203                 :            : }
    5204                 :            : 
    5205                 :            : /**
    5206                 :            :  * Create action push VLAN.
    5207                 :            :  *
    5208                 :            :  * @param[in] dev
    5209                 :            :  *   Pointer to rte_eth_dev structure.
    5210                 :            :  * @param[in] attr
    5211                 :            :  *   Pointer to the flow attributes.
    5212                 :            :  * @param[in] vlan
    5213                 :            :  *   Pointer to the vlan to push to the Ethernet header.
    5214                 :            :  * @param[in, out] dev_flow
    5215                 :            :  *   Pointer to the mlx5_flow.
    5216                 :            :  * @param[out] error
    5217                 :            :  *   Pointer to the error structure.
    5218                 :            :  *
    5219                 :            :  * @return
    5220                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5221                 :            :  */
    5222                 :            : static int
    5223         [ #  # ]:          0 : flow_dv_create_action_push_vlan(struct rte_eth_dev *dev,
    5224                 :            :                                 const struct rte_flow_attr *attr,
    5225                 :            :                                 const struct rte_vlan_hdr *vlan,
    5226                 :            :                                 struct mlx5_flow *dev_flow,
    5227                 :            :                                 struct rte_flow_error *error)
    5228                 :            : {
    5229                 :            :         struct mlx5_flow_dv_push_vlan_action_resource res;
    5230                 :            : 
    5231                 :            :         memset(&res, 0, sizeof(res));
    5232                 :          0 :         res.vlan_tag =
    5233         [ #  # ]:          0 :                 rte_cpu_to_be_32(((uint32_t)vlan->eth_proto) << 16 |
    5234                 :            :                                  vlan->vlan_tci);
    5235         [ #  # ]:          0 :         if (attr->transfer)
    5236                 :          0 :                 res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
    5237                 :            :         else
    5238                 :          0 :                 res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
    5239                 :            :                                              MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
    5240                 :          0 :         return flow_dv_push_vlan_action_resource_register
    5241                 :            :                                             (dev, &res, dev_flow, error);
    5242                 :            : }
    5243                 :            : 
    5244                 :            : /**
    5245                 :            :  * Validate the modify-header actions.
    5246                 :            :  *
    5247                 :            :  * @param[in] action_flags
    5248                 :            :  *   Holds the actions detected until now.
    5249                 :            :  * @param[in] action
    5250                 :            :  *   Pointer to the modify action.
    5251                 :            :  * @param[out] error
    5252                 :            :  *   Pointer to error structure.
    5253                 :            :  *
    5254                 :            :  * @return
    5255                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5256                 :            :  */
    5257                 :            : static int
    5258                 :          0 : flow_dv_validate_action_modify_hdr(const uint64_t action_flags,
    5259                 :            :                                    const struct rte_flow_action *action,
    5260                 :            :                                    struct rte_flow_error *error)
    5261                 :            : {
    5262   [ #  #  #  # ]:          0 :         if (action->type != RTE_FLOW_ACTION_TYPE_DEC_TTL && !action->conf)
    5263                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5264                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5265                 :            :                                           NULL, "action configuration not set");
    5266                 :            : 
    5267         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    5268                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5269                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5270                 :            :                                           "can't have encap action before"
    5271                 :            :                                           " modify action");
    5272                 :            :         return 0;
    5273                 :            : }
    5274                 :            : 
    5275                 :            : /**
    5276                 :            :  * Validate the modify-header MAC address actions.
    5277                 :            :  *
    5278                 :            :  * @param[in] action_flags
    5279                 :            :  *   Holds the actions detected until now.
    5280                 :            :  * @param[in] action
    5281                 :            :  *   Pointer to the modify action.
    5282                 :            :  * @param[in] item_flags
    5283                 :            :  *   Holds the items detected.
    5284                 :            :  * @param[out] error
    5285                 :            :  *   Pointer to error structure.
    5286                 :            :  *
    5287                 :            :  * @return
    5288                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5289                 :            :  */
    5290                 :            : static int
    5291                 :          0 : flow_dv_validate_action_modify_mac(const uint64_t action_flags,
    5292                 :            :                                    const struct rte_flow_action *action,
    5293                 :            :                                    const uint64_t item_flags,
    5294                 :            :                                    struct rte_flow_error *error)
    5295                 :            : {
    5296                 :            :         int ret = 0;
    5297                 :            : 
    5298                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5299         [ #  # ]:          0 :         if (!ret) {
    5300         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L2))
    5301                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5302                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5303                 :            :                                                   NULL,
    5304                 :            :                                                   "no L2 item in pattern");
    5305                 :            :         }
    5306                 :            :         return ret;
    5307                 :            : }
    5308                 :            : 
    5309                 :            : /**
    5310                 :            :  * Validate the modify-header IPv4 address actions.
    5311                 :            :  *
    5312                 :            :  * @param[in] action_flags
    5313                 :            :  *   Holds the actions detected until now.
    5314                 :            :  * @param[in] action
    5315                 :            :  *   Pointer to the modify action.
    5316                 :            :  * @param[in] item_flags
    5317                 :            :  *   Holds the items detected.
    5318                 :            :  * @param[out] error
    5319                 :            :  *   Pointer to error structure.
    5320                 :            :  *
    5321                 :            :  * @return
    5322                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5323                 :            :  */
    5324                 :            : static int
    5325                 :          0 : flow_dv_validate_action_modify_ipv4(const uint64_t action_flags,
    5326                 :            :                                     const struct rte_flow_action *action,
    5327                 :            :                                     const uint64_t item_flags,
    5328                 :            :                                     struct rte_flow_error *error)
    5329                 :            : {
    5330                 :            :         int ret = 0;
    5331                 :            :         uint64_t layer;
    5332                 :            : 
    5333                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5334         [ #  # ]:          0 :         if (!ret) {
    5335                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5336         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    5337                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    5338         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5339                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5340                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5341                 :            :                                                   NULL,
    5342                 :            :                                                   "no ipv4 item in pattern");
    5343                 :            :         }
    5344                 :            :         return ret;
    5345                 :            : }
    5346                 :            : 
    5347                 :            : /**
    5348                 :            :  * Validate the modify-header IPv6 address actions.
    5349                 :            :  *
    5350                 :            :  * @param[in] action_flags
    5351                 :            :  *   Holds the actions detected until now.
    5352                 :            :  * @param[in] action
    5353                 :            :  *   Pointer to the modify action.
    5354                 :            :  * @param[in] item_flags
    5355                 :            :  *   Holds the items detected.
    5356                 :            :  * @param[out] error
    5357                 :            :  *   Pointer to error structure.
    5358                 :            :  *
    5359                 :            :  * @return
    5360                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5361                 :            :  */
    5362                 :            : static int
    5363                 :          0 : flow_dv_validate_action_modify_ipv6(const uint64_t action_flags,
    5364                 :            :                                     const struct rte_flow_action *action,
    5365                 :            :                                     const uint64_t item_flags,
    5366                 :            :                                     struct rte_flow_error *error)
    5367                 :            : {
    5368                 :            :         int ret = 0;
    5369                 :            :         uint64_t layer;
    5370                 :            : 
    5371                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5372         [ #  # ]:          0 :         if (!ret) {
    5373                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5374         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    5375                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    5376         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5377                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5378                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5379                 :            :                                                   NULL,
    5380                 :            :                                                   "no ipv6 item in pattern");
    5381                 :            :         }
    5382                 :            :         return ret;
    5383                 :            : }
    5384                 :            : 
    5385                 :            : /**
    5386                 :            :  * Validate the modify-header TP actions.
    5387                 :            :  *
    5388                 :            :  * @param[in] action_flags
    5389                 :            :  *   Holds the actions detected until now.
    5390                 :            :  * @param[in] action
    5391                 :            :  *   Pointer to the modify action.
    5392                 :            :  * @param[in] item_flags
    5393                 :            :  *   Holds the items detected.
    5394                 :            :  * @param[out] error
    5395                 :            :  *   Pointer to error structure.
    5396                 :            :  *
    5397                 :            :  * @return
    5398                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5399                 :            :  */
    5400                 :            : static int
    5401                 :          0 : flow_dv_validate_action_modify_tp(const uint64_t action_flags,
    5402                 :            :                                   const struct rte_flow_action *action,
    5403                 :            :                                   const uint64_t item_flags,
    5404                 :            :                                   struct rte_flow_error *error)
    5405                 :            : {
    5406                 :            :         int ret = 0;
    5407                 :            :         uint64_t layer;
    5408                 :            : 
    5409                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5410         [ #  # ]:          0 :         if (!ret) {
    5411                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5412         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4 :
    5413                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4;
    5414         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5415                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5416                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5417                 :            :                                                   NULL, "no transport layer "
    5418                 :            :                                                   "in pattern");
    5419                 :            :         }
    5420                 :            :         return ret;
    5421                 :            : }
    5422                 :            : 
    5423                 :            : /**
    5424                 :            :  * Validate the modify-header actions of increment/decrement
    5425                 :            :  * TCP Sequence-number.
    5426                 :            :  *
    5427                 :            :  * @param[in] action_flags
    5428                 :            :  *   Holds the actions detected until now.
    5429                 :            :  * @param[in] action
    5430                 :            :  *   Pointer to the modify action.
    5431                 :            :  * @param[in] item_flags
    5432                 :            :  *   Holds the items detected.
    5433                 :            :  * @param[out] error
    5434                 :            :  *   Pointer to error structure.
    5435                 :            :  *
    5436                 :            :  * @return
    5437                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5438                 :            :  */
    5439                 :            : static int
    5440                 :          0 : flow_dv_validate_action_modify_tcp_seq(const uint64_t action_flags,
    5441                 :            :                                        const struct rte_flow_action *action,
    5442                 :            :                                        const uint64_t item_flags,
    5443                 :            :                                        struct rte_flow_error *error)
    5444                 :            : {
    5445                 :            :         int ret = 0;
    5446                 :            :         uint64_t layer;
    5447                 :            : 
    5448                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5449         [ #  # ]:          0 :         if (!ret) {
    5450                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5451         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4_TCP :
    5452                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4_TCP;
    5453         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5454                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5455                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5456                 :            :                                                   NULL, "no TCP item in"
    5457                 :            :                                                   " pattern");
    5458         [ #  # ]:          0 :                 if ((action->type == RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ &&
    5459   [ #  #  #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_DEC_TCP_SEQ)) ||
    5460                 :          0 :                     (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ &&
    5461         [ #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_INC_TCP_SEQ)))
    5462                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5463                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5464                 :            :                                                   NULL,
    5465                 :            :                                                   "cannot decrease and increase"
    5466                 :            :                                                   " TCP sequence number"
    5467                 :            :                                                   " at the same time");
    5468                 :            :         }
    5469                 :            :         return ret;
    5470                 :            : }
    5471                 :            : 
    5472                 :            : /**
    5473                 :            :  * Validate the modify-header actions of increment/decrement
    5474                 :            :  * TCP Acknowledgment number.
    5475                 :            :  *
    5476                 :            :  * @param[in] action_flags
    5477                 :            :  *   Holds the actions detected until now.
    5478                 :            :  * @param[in] action
    5479                 :            :  *   Pointer to the modify action.
    5480                 :            :  * @param[in] item_flags
    5481                 :            :  *   Holds the items detected.
    5482                 :            :  * @param[out] error
    5483                 :            :  *   Pointer to error structure.
    5484                 :            :  *
    5485                 :            :  * @return
    5486                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5487                 :            :  */
    5488                 :            : static int
    5489                 :          0 : flow_dv_validate_action_modify_tcp_ack(const uint64_t action_flags,
    5490                 :            :                                        const struct rte_flow_action *action,
    5491                 :            :                                        const uint64_t item_flags,
    5492                 :            :                                        struct rte_flow_error *error)
    5493                 :            : {
    5494                 :            :         int ret = 0;
    5495                 :            :         uint64_t layer;
    5496                 :            : 
    5497                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5498         [ #  # ]:          0 :         if (!ret) {
    5499                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5500         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4_TCP :
    5501                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4_TCP;
    5502         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5503                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5504                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5505                 :            :                                                   NULL, "no TCP item in"
    5506                 :            :                                                   " pattern");
    5507         [ #  # ]:          0 :                 if ((action->type == RTE_FLOW_ACTION_TYPE_INC_TCP_ACK &&
    5508   [ #  #  #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_DEC_TCP_ACK)) ||
    5509                 :          0 :                     (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK &&
    5510         [ #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_INC_TCP_ACK)))
    5511                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5512                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5513                 :            :                                                   NULL,
    5514                 :            :                                                   "cannot decrease and increase"
    5515                 :            :                                                   " TCP acknowledgment number"
    5516                 :            :                                                   " at the same time");
    5517                 :            :         }
    5518                 :            :         return ret;
    5519                 :            : }
    5520                 :            : 
    5521                 :            : /**
    5522                 :            :  * Validate the modify-header TTL actions.
    5523                 :            :  *
    5524                 :            :  * @param[in] action_flags
    5525                 :            :  *   Holds the actions detected until now.
    5526                 :            :  * @param[in] action
    5527                 :            :  *   Pointer to the modify action.
    5528                 :            :  * @param[in] item_flags
    5529                 :            :  *   Holds the items detected.
    5530                 :            :  * @param[out] error
    5531                 :            :  *   Pointer to error structure.
    5532                 :            :  *
    5533                 :            :  * @return
    5534                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5535                 :            :  */
    5536                 :            : static int
    5537                 :          0 : flow_dv_validate_action_modify_ttl(const uint64_t action_flags,
    5538                 :            :                                    const struct rte_flow_action *action,
    5539                 :            :                                    const uint64_t item_flags,
    5540                 :            :                                    struct rte_flow_error *error)
    5541                 :            : {
    5542                 :            :         int ret = 0;
    5543                 :            :         uint64_t layer;
    5544                 :            : 
    5545                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5546         [ #  # ]:          0 :         if (!ret) {
    5547                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5548         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3 :
    5549                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3;
    5550         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5551                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5552                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5553                 :            :                                                   NULL,
    5554                 :            :                                                   "no IP protocol in pattern");
    5555                 :            :         }
    5556                 :            :         return ret;
    5557                 :            : }
    5558                 :            : 
    5559                 :            : /**
    5560                 :            :  * Validate the generic modify field actions.
    5561                 :            :  * @param[in] dev
    5562                 :            :  *   Pointer to the rte_eth_dev structure.
    5563                 :            :  * @param[in] action_flags
    5564                 :            :  *   Holds the actions detected until now.
    5565                 :            :  * @param[in] action
    5566                 :            :  *   Pointer to the modify action.
    5567                 :            :  * @param[in] attr
    5568                 :            :  *   Pointer to the flow attributes.
    5569                 :            :  * @param root
    5570                 :            :  *   Whether action is on root table.
    5571                 :            :  * @param[out] error
    5572                 :            :  *   Pointer to error structure.
    5573                 :            :  *
    5574                 :            :  * @return
    5575                 :            :  *   Number of header fields to modify (0 or more) on success,
    5576                 :            :  *   a negative errno value otherwise and rte_errno is set.
    5577                 :            :  */
    5578                 :            : static int
    5579                 :          0 : flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
    5580                 :            :                                    const uint64_t action_flags,
    5581                 :            :                                    const struct rte_flow_action *action,
    5582                 :            :                                    const struct rte_flow_attr *attr,
    5583                 :            :                                    bool root,
    5584                 :            :                                    struct rte_flow_error *error)
    5585                 :            : {
    5586                 :            :         int ret = 0;
    5587                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5588                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    5589                 :          0 :         struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
    5590                 :          0 :         const struct rte_flow_action_modify_field *conf = action->conf;
    5591                 :          0 :         const struct rte_flow_field_data *src_data = &conf->src;
    5592                 :          0 :         const struct rte_flow_field_data *dst_data = &conf->dst;
    5593                 :          0 :         uint32_t dst_width, src_width, width = conf->width;
    5594                 :            : 
    5595                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5596         [ #  # ]:          0 :         if (ret)
    5597                 :            :                 return ret;
    5598         [ #  # ]:          0 :         if (src_data->field == RTE_FLOW_FIELD_FLEX_ITEM ||
    5599         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_FLEX_ITEM)
    5600                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5601                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5602                 :            :                                 "flex item fields modification"
    5603                 :            :                                 " is not supported");
    5604                 :          0 :         dst_width = mlx5_flow_item_field_width(dev, dst_data->field,
    5605                 :            :                                                -1, attr, error);
    5606                 :          0 :         src_width = mlx5_flow_item_field_width(dev, src_data->field,
    5607                 :            :                                                dst_width, attr, error);
    5608         [ #  # ]:          0 :         if (width == 0)
    5609                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5610                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5611                 :            :                                 "no bits are requested to be modified");
    5612         [ #  # ]:          0 :         else if (width > dst_width || width > src_width)
    5613                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5614                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5615                 :            :                                 "cannot modify more bits than"
    5616                 :            :                                 " the width of a field");
    5617         [ #  # ]:          0 :         if (dst_data->field != RTE_FLOW_FIELD_VALUE &&
    5618                 :            :             dst_data->field != RTE_FLOW_FIELD_POINTER) {
    5619         [ #  # ]:          0 :                 if (dst_data->offset + width > dst_width)
    5620                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5621                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5622                 :            :                                         "destination offset is too big");
    5623                 :          0 :                 ret = flow_validate_modify_field_level(dst_data, error);
    5624         [ #  # ]:          0 :                 if (ret)
    5625                 :            :                         return ret;
    5626         [ #  # ]:          0 :                 if (dst_data->tag_index &&
    5627         [ #  # ]:          0 :                     !flow_modify_field_support_tag_array(dst_data->field))
    5628                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5629                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5630                 :            :                                         "destination tag index is not supported");
    5631         [ #  # ]:          0 :                 if (dst_data->class_id)
    5632                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5633                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5634                 :            :                                         "destination class ID is not supported");
    5635                 :            :         }
    5636         [ #  # ]:          0 :         if (src_data->field != RTE_FLOW_FIELD_VALUE &&
    5637                 :            :             src_data->field != RTE_FLOW_FIELD_POINTER) {
    5638         [ #  # ]:          0 :                 if (root)
    5639                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5640                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5641                 :            :                                         "modify field action is not"
    5642                 :            :                                         " supported for group 0");
    5643         [ #  # ]:          0 :                 if (src_data->offset + width > src_width)
    5644                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5645                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5646                 :            :                                         "source offset is too big");
    5647                 :          0 :                 ret = flow_validate_modify_field_level(src_data, error);
    5648         [ #  # ]:          0 :                 if (ret)
    5649                 :            :                         return ret;
    5650         [ #  # ]:          0 :                 if (src_data->tag_index &&
    5651         [ #  # ]:          0 :                     !flow_modify_field_support_tag_array(src_data->field))
    5652                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5653                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5654                 :            :                                         "source tag index is not supported");
    5655         [ #  # ]:          0 :                 if (src_data->class_id)
    5656                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5657                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5658                 :            :                                         "source class ID is not supported");
    5659                 :            :         }
    5660         [ #  # ]:          0 :         if ((dst_data->field == src_data->field) &&
    5661         [ #  # ]:          0 :             (dst_data->level == src_data->level))
    5662                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5663                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5664                 :            :                                 "source and destination fields"
    5665                 :            :                                 " cannot be the same");
    5666                 :          0 :         if (dst_data->field == RTE_FLOW_FIELD_VALUE ||
    5667         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_POINTER ||
    5668                 :            :             dst_data->field == RTE_FLOW_FIELD_MARK)
    5669                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5670                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5671                 :            :                                 "mark, immediate value or a pointer to it"
    5672                 :            :                                 " cannot be used as a destination");
    5673   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_START ||
    5674                 :            :             src_data->field == RTE_FLOW_FIELD_START)
    5675                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5676                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5677                 :            :                                 "modifications of an arbitrary"
    5678                 :            :                                 " place in a packet is not supported");
    5679   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_VLAN_TYPE ||
    5680                 :            :             src_data->field == RTE_FLOW_FIELD_VLAN_TYPE)
    5681                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5682                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5683                 :            :                                 "modifications of the 802.1Q Tag"
    5684                 :            :                                 " Identifier is not supported");
    5685   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_VXLAN_VNI ||
    5686                 :            :             src_data->field == RTE_FLOW_FIELD_VXLAN_VNI)
    5687                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5688                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5689                 :            :                                 "modifications of the VXLAN Network"
    5690                 :            :                                 " Identifier is not supported");
    5691   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_VNI ||
    5692                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_VNI)
    5693                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5694                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5695                 :            :                                 "modifications of the GENEVE Network"
    5696                 :            :                                 " Identifier is not supported");
    5697   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE ||
    5698                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE)
    5699                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5700                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5701                 :            :                                 "modifications of the GENEVE option type is not supported");
    5702   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS ||
    5703                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS)
    5704                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5705                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5706                 :            :                                 "modifications of the GENEVE option class is not supported");
    5707   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_DATA ||
    5708                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_DATA)
    5709                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5710                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5711                 :            :                                 "modifications of the GENEVE option data is not supported");
    5712   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_MPLS ||
    5713                 :            :             src_data->field == RTE_FLOW_FIELD_MPLS)
    5714                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5715                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5716                 :            :                                 "modifications of the MPLS header "
    5717                 :            :                                 "is not supported");
    5718   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_RANDOM ||
    5719                 :            :             src_data->field == RTE_FLOW_FIELD_RANDOM)
    5720                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5721                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5722                 :            :                                 "modifications of random value is not supported");
    5723         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_MARK ||
    5724                 :            :             src_data->field == RTE_FLOW_FIELD_MARK)
    5725   [ #  #  #  # ]:          0 :                 if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
    5726                 :          0 :                     !mlx5_flow_ext_mreg_supported(dev))
    5727                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5728                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5729                 :            :                                         "cannot modify mark in legacy mode"
    5730                 :            :                                         " or without extensive registers");
    5731         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_META ||
    5732         [ #  # ]:          0 :             src_data->field == RTE_FLOW_FIELD_META) {
    5733   [ #  #  #  # ]:          0 :                 if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    5734                 :          0 :                     !mlx5_flow_ext_mreg_supported(dev))
    5735                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5736                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5737                 :            :                                         "cannot modify meta without"
    5738                 :            :                                         " extensive registers support");
    5739                 :          0 :                 ret = flow_dv_get_metadata_reg(dev, attr, error);
    5740         [ #  # ]:          0 :                 if (ret < 0 || ret == REG_NON)
    5741                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5742                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5743                 :            :                                         "cannot modify meta without"
    5744                 :            :                                         " extensive registers available");
    5745                 :            :         }
    5746         [ #  # ]:          0 :         if (conf->operation == RTE_FLOW_MODIFY_SUB)
    5747                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5748                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5749                 :            :                                 "sub operations are not supported");
    5750         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_IPV4_ECN ||
    5751   [ #  #  #  # ]:          0 :             src_data->field == RTE_FLOW_FIELD_IPV4_ECN ||
    5752         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_IPV6_ECN ||
    5753                 :            :             src_data->field == RTE_FLOW_FIELD_IPV6_ECN)
    5754   [ #  #  #  # ]:          0 :                 if (!hca_attr->modify_outer_ip_ecn && root)
    5755                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5756                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5757                 :            :                                 "modifications of the ECN for current firmware is not supported");
    5758                 :          0 :         return (width / 32) + !!(width % 32);
    5759                 :            : }
    5760                 :            : 
    5761                 :            : /**
    5762                 :            :  * Validate jump action.
    5763                 :            :  *
    5764                 :            :  * @param[in] action
    5765                 :            :  *   Pointer to the jump action.
    5766                 :            :  * @param[in] action_flags
    5767                 :            :  *   Holds the actions detected until now.
    5768                 :            :  * @param[in] attributes
    5769                 :            :  *   Pointer to flow attributes
    5770                 :            :  * @param[in] external
    5771                 :            :  *   Action belongs to flow rule created by request external to PMD.
    5772                 :            :  * @param[out] error
    5773                 :            :  *   Pointer to error structure.
    5774                 :            :  *
    5775                 :            :  * @return
    5776                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5777                 :            :  */
    5778                 :            : static int
    5779                 :          0 : flow_dv_validate_action_jump(struct rte_eth_dev *dev,
    5780                 :            :                              const struct mlx5_flow_tunnel *tunnel,
    5781                 :            :                              const struct rte_flow_action *action,
    5782                 :            :                              uint64_t action_flags,
    5783                 :            :                              const struct rte_flow_attr *attributes,
    5784                 :            :                              bool external, struct rte_flow_error *error)
    5785                 :            : {
    5786                 :          0 :         uint32_t target_group, table = 0;
    5787                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5788                 :            :         int ret = 0;
    5789                 :          0 :         struct flow_grp_info grp_info = {
    5790                 :            :                 .external = !!external,
    5791                 :          0 :                 .transfer = !!attributes->transfer,
    5792                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
    5793                 :            :                 .std_tbl_fix = 0
    5794                 :            :         };
    5795         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
    5796                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    5797                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5798                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5799                 :            :                                           "can't have 2 fate actions in"
    5800                 :            :                                           " same flow");
    5801         [ #  # ]:          0 :         if (!action->conf)
    5802                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5803                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5804                 :            :                                           NULL, "action configuration not set");
    5805                 :          0 :         target_group =
    5806                 :            :                 ((const struct rte_flow_action_jump *)action->conf)->group;
    5807                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, target_group, &table,
    5808                 :            :                                        &grp_info, error);
    5809         [ #  # ]:          0 :         if (ret)
    5810                 :            :                 return ret;
    5811         [ #  # ]:          0 :         if (table == 0)
    5812                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5813                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5814                 :            :                                           NULL, "root table shouldn't be destination");
    5815                 :            :         return 0;
    5816                 :            : }
    5817                 :            : 
    5818                 :            : /*
    5819                 :            :  * Validate action PORT_ID / REPRESENTED_PORT.
    5820                 :            :  *
    5821                 :            :  * @param[in] dev
    5822                 :            :  *   Pointer to rte_eth_dev structure.
    5823                 :            :  * @param[in] action_flags
    5824                 :            :  *   Bit-fields that holds the actions detected until now.
    5825                 :            :  * @param[in] action
    5826                 :            :  *   PORT_ID / REPRESENTED_PORT action structure.
    5827                 :            :  * @param[in] attr
    5828                 :            :  *   Attributes of flow that includes this action.
    5829                 :            :  * @param[out] error
    5830                 :            :  *   Pointer to error structure.
    5831                 :            :  *
    5832                 :            :  * @return
    5833                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5834                 :            :  */
    5835                 :            : static int
    5836                 :          0 : flow_dv_validate_action_port_id(struct rte_eth_dev *dev,
    5837                 :            :                                 uint64_t action_flags,
    5838                 :            :                                 const struct rte_flow_action *action,
    5839                 :            :                                 const struct rte_flow_attr *attr,
    5840                 :            :                                 struct rte_flow_error *error)
    5841                 :            : {
    5842                 :            :         const struct rte_flow_action_port_id *port_id;
    5843                 :            :         const struct rte_flow_action_ethdev *ethdev;
    5844                 :            :         struct mlx5_priv *act_priv;
    5845                 :            :         struct mlx5_priv *dev_priv;
    5846                 :            :         uint16_t port;
    5847                 :            : 
    5848         [ #  # ]:          0 :         if (!attr->transfer)
    5849                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5850                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5851                 :            :                                           NULL,
    5852                 :            :                                           "port action is valid in transfer"
    5853                 :            :                                           " mode only");
    5854   [ #  #  #  # ]:          0 :         if (!action || !action->conf)
    5855                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5856                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5857                 :            :                                           NULL,
    5858                 :            :                                           "port action parameters must be"
    5859                 :            :                                           " specified");
    5860         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
    5861                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    5862                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5863                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5864                 :            :                                           "can have only one fate actions in"
    5865                 :            :                                           " a flow");
    5866                 :          0 :         dev_priv = mlx5_dev_to_eswitch_info(dev);
    5867         [ #  # ]:          0 :         if (!dev_priv)
    5868                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    5869                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5870                 :            :                                           NULL,
    5871                 :            :                                           "failed to obtain E-Switch info");
    5872      [ #  #  # ]:          0 :         switch (action->type) {
    5873                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID:
    5874                 :          0 :                 port_id = action->conf;
    5875         [ #  # ]:          0 :                 port = port_id->original ? dev->data->port_id : port_id->id;
    5876                 :            :                 break;
    5877                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    5878                 :          0 :                 ethdev = action->conf;
    5879                 :          0 :                 port = ethdev->port_id;
    5880                 :          0 :                 break;
    5881                 :          0 :         default:
    5882                 :            :                 MLX5_ASSERT(false);
    5883                 :          0 :                 return rte_flow_error_set
    5884                 :            :                                 (error, EINVAL,
    5885                 :            :                                  RTE_FLOW_ERROR_TYPE_ACTION, action,
    5886                 :            :                                  "unknown E-Switch action");
    5887                 :            :         }
    5888                 :          0 :         act_priv = mlx5_port_to_eswitch_info(port, false);
    5889         [ #  # ]:          0 :         if (!act_priv)
    5890                 :          0 :                 return rte_flow_error_set
    5891                 :            :                                 (error, rte_errno,
    5892                 :          0 :                                  RTE_FLOW_ERROR_TYPE_ACTION_CONF, action->conf,
    5893                 :            :                                  "failed to obtain E-Switch port id for port");
    5894         [ #  # ]:          0 :         if (act_priv->domain_id != dev_priv->domain_id)
    5895                 :          0 :                 return rte_flow_error_set
    5896                 :            :                                 (error, EINVAL,
    5897                 :            :                                  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5898                 :            :                                  "port does not belong to"
    5899                 :            :                                  " E-Switch being configured");
    5900                 :            :         return 0;
    5901                 :            : }
    5902                 :            : 
    5903                 :            : /**
    5904                 :            :  * Get the maximum number of modify header actions.
    5905                 :            :  *
    5906                 :            :  * @param dev
    5907                 :            :  *   Pointer to rte_eth_dev structure.
    5908                 :            :  * @param root
    5909                 :            :  *   Whether action is on root table.
    5910                 :            :  *
    5911                 :            :  * @return
    5912                 :            :  *   Max number of modify header actions device can support.
    5913                 :            :  */
    5914                 :            : static inline unsigned int
    5915                 :            : flow_dv_modify_hdr_action_max(struct rte_eth_dev *dev __rte_unused,
    5916                 :            :                               bool root)
    5917                 :            : {
    5918                 :            :         /*
    5919                 :            :          * There's no way to directly query the max capacity from FW.
    5920                 :            :          * The maximal value on root table should be assumed to be supported.
    5921                 :            :          */
    5922         [ #  # ]:          0 :         if (!root)
    5923                 :            :                 return MLX5_MAX_MODIFY_NUM;
    5924                 :            :         else
    5925                 :          0 :                 return MLX5_ROOT_TBL_MODIFY_NUM;
    5926                 :            : }
    5927                 :            : 
    5928                 :            : /**
    5929                 :            :  * Validate the meter action.
    5930                 :            :  *
    5931                 :            :  * @param[in] dev
    5932                 :            :  *   Pointer to rte_eth_dev structure.
    5933                 :            :  * @param[in] action_flags
    5934                 :            :  *   Bit-fields that holds the actions detected until now.
    5935                 :            :  * @param[in] item_flags
    5936                 :            :  *   Holds the items detected.
    5937                 :            :  * @param[in] action
    5938                 :            :  *   Pointer to the meter action.
    5939                 :            :  * @param[in] attr
    5940                 :            :  *   Attributes of flow that includes this action.
    5941                 :            :  * @param[in] port_id_item
    5942                 :            :  *   Pointer to item indicating port id.
    5943                 :            :  * @param[out] error
    5944                 :            :  *   Pointer to error structure.
    5945                 :            :  *
    5946                 :            :  * @return
    5947                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5948                 :            :  */
    5949                 :            : static int
    5950                 :          0 : mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,
    5951                 :            :                                 uint64_t action_flags, uint64_t item_flags,
    5952                 :            :                                 const struct rte_flow_action *action,
    5953                 :            :                                 const struct rte_flow_attr *attr,
    5954                 :            :                                 const struct rte_flow_item *port_id_item,
    5955                 :            :                                 bool *def_policy,
    5956                 :            :                                 struct rte_flow_error *error)
    5957                 :            : {
    5958                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5959                 :          0 :         const struct rte_flow_action_meter *am = action->conf;
    5960                 :            :         struct mlx5_flow_meter_info *fm;
    5961                 :            :         struct mlx5_flow_meter_policy *mtr_policy;
    5962                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
    5963                 :          0 :         uint16_t flow_src_port = priv->representor_id;
    5964                 :          0 :         bool all_ports = false;
    5965                 :            : 
    5966         [ #  # ]:          0 :         if (!am)
    5967                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5968                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5969                 :            :                                           "meter action conf is NULL");
    5970                 :            : 
    5971         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_METER)
    5972                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5973                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5974                 :            :                                           "meter chaining not support");
    5975         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_JUMP)
    5976                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5977                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5978                 :            :                                           "meter with jump not support");
    5979         [ #  # ]:          0 :         if (!priv->mtr_en)
    5980                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5981                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5982                 :            :                                           NULL,
    5983                 :            :                                           "meter action not supported");
    5984                 :          0 :         fm = mlx5_flow_meter_find(priv, am->mtr_id, NULL);
    5985         [ #  # ]:          0 :         if (!fm)
    5986                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5987                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5988                 :            :                                           "Meter not found");
    5989                 :            :         /* aso meter can always be shared by different domains */
    5990   [ #  #  #  # ]:          0 :         if (fm->ref_cnt && !priv->sh->meter_aso_en &&
    5991         [ #  # ]:          0 :             !(fm->transfer == attr->transfer ||
    5992   [ #  #  #  # ]:          0 :               (!fm->ingress && !attr->ingress && attr->egress) ||
    5993   [ #  #  #  # ]:          0 :               (!fm->egress && !attr->egress && attr->ingress)))
    5994                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5995                 :            :                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5996                 :            :                         "Flow attributes domain are either invalid "
    5997                 :            :                         "or have a domain conflict with current "
    5998                 :            :                         "meter attributes");
    5999         [ #  # ]:          0 :         if (fm->def_policy) {
    6000         [ #  # ]:          0 :                 if (!((attr->transfer &&
    6001         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_TRANSFER]) ||
    6002         [ #  # ]:          0 :                         (attr->egress &&
    6003         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_EGRESS]) ||
    6004         [ #  # ]:          0 :                         (attr->ingress &&
    6005         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_INGRESS])))
    6006                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6007                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6008                 :            :                                           "Flow attributes domain "
    6009                 :            :                                           "have a conflict with current "
    6010                 :            :                                           "meter domain attributes");
    6011                 :          0 :                 *def_policy = true;
    6012                 :            :         } else {
    6013                 :          0 :                 mtr_policy = mlx5_flow_meter_policy_find(dev,
    6014                 :            :                                                 fm->policy_id, NULL);
    6015         [ #  # ]:          0 :                 if (!mtr_policy)
    6016                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6017                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6018                 :            :                                           "Invalid policy id for meter ");
    6019   [ #  #  #  # ]:          0 :                 if (!((attr->transfer && mtr_policy->transfer) ||
    6020   [ #  #  #  # ]:          0 :                         (attr->egress && mtr_policy->egress) ||
    6021   [ #  #  #  # ]:          0 :                         (attr->ingress && mtr_policy->ingress)))
    6022                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6023                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6024                 :            :                                           "Flow attributes domain "
    6025                 :            :                                           "have a conflict with current "
    6026                 :            :                                           "meter domain attributes");
    6027         [ #  # ]:          0 :                 if (port_id_item) {
    6028         [ #  # ]:          0 :                         if (mlx5_flow_get_item_vport_id(dev, port_id_item, &flow_src_port,
    6029                 :            :                                                         &all_ports, error))
    6030                 :          0 :                                 return -rte_errno;
    6031                 :            :                 }
    6032         [ #  # ]:          0 :                 if (attr->transfer) {
    6033                 :            :                         /* When flow matching all src ports, meter should not have drop count. */
    6034   [ #  #  #  #  :          0 :                         if (all_ports && (fm->drop_cnt || mtr_policy->hierarchy_match_port))
                   #  # ]
    6035                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6036                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    6037                 :            :                                                           "Meter drop count or "
    6038                 :            :                                                           "modify_field/set_tag in meter hierarchy "
    6039                 :            :                                                           "not supported when matching all ports.");
    6040         [ #  # ]:          0 :                 } else if (mtr_policy->is_rss) {
    6041                 :            :                         struct mlx5_flow_meter_policy *fp;
    6042                 :            :                         struct mlx5_meter_policy_action_container *acg;
    6043                 :            :                         struct mlx5_meter_policy_action_container *acy;
    6044                 :            :                         const struct rte_flow_action *rss_act;
    6045                 :            :                         int ret;
    6046                 :            : 
    6047                 :          0 :                         fp = mlx5_flow_meter_hierarchy_get_final_policy(dev,
    6048                 :            :                                                                 mtr_policy);
    6049         [ #  # ]:          0 :                         if (fp == NULL)
    6050                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6051                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6052                 :            :                                                   "Unable to get the final "
    6053                 :            :                                                   "policy in the hierarchy");
    6054                 :            :                         acg = &fp->act_cnt[RTE_COLOR_GREEN];
    6055                 :            :                         acy = &fp->act_cnt[RTE_COLOR_YELLOW];
    6056                 :            :                         MLX5_ASSERT(acg->fate_action ==
    6057                 :            :                                     MLX5_FLOW_FATE_SHARED_RSS ||
    6058                 :            :                                     acy->fate_action ==
    6059                 :            :                                     MLX5_FLOW_FATE_SHARED_RSS);
    6060         [ #  # ]:          0 :                         if (acg->fate_action == MLX5_FLOW_FATE_SHARED_RSS)
    6061                 :          0 :                                 rss_act = acg->rss;
    6062                 :            :                         else
    6063                 :          0 :                                 rss_act = acy->rss;
    6064                 :          0 :                         ret = mlx5_flow_validate_action_rss(rss_act,
    6065                 :            :                                         action_flags, dev, attr,
    6066                 :            :                                         item_flags, error);
    6067         [ #  # ]:          0 :                         if (ret)
    6068                 :            :                                 return ret;
    6069                 :            :                 }
    6070                 :          0 :                 *def_policy = false;
    6071                 :            :         }
    6072                 :            :         return 0;
    6073                 :            : }
    6074                 :            : 
    6075                 :            : /**
    6076                 :            :  * Validate the age action.
    6077                 :            :  *
    6078                 :            :  * @param[in] action_flags
    6079                 :            :  *   Holds the actions detected until now.
    6080                 :            :  * @param[in] action
    6081                 :            :  *   Pointer to the age action.
    6082                 :            :  * @param[in] dev
    6083                 :            :  *   Pointer to the Ethernet device structure.
    6084                 :            :  * @param[out] error
    6085                 :            :  *   Pointer to error structure.
    6086                 :            :  *
    6087                 :            :  * @return
    6088                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6089                 :            :  */
    6090                 :            : static int
    6091                 :          0 : flow_dv_validate_action_age(uint64_t action_flags,
    6092                 :            :                             const struct rte_flow_action *action,
    6093                 :            :                             struct rte_eth_dev *dev,
    6094                 :            :                             struct rte_flow_error *error)
    6095                 :            : {
    6096                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6097                 :          0 :         const struct rte_flow_action_age *age = action->conf;
    6098                 :            : 
    6099         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx ||
    6100   [ #  #  #  # ]:          0 :             (priv->sh->sws_cmng.counter_fallback && !priv->sh->aso_age_mng))
    6101                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6102                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6103                 :            :                                           NULL,
    6104                 :            :                                           "age action not supported");
    6105         [ #  # ]:          0 :         if (!(action->conf))
    6106                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6107                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6108                 :            :                                           "configuration cannot be null");
    6109         [ #  # ]:          0 :         if (!(age->timeout))
    6110                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6111                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6112                 :            :                                           "invalid timeout value 0");
    6113         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_AGE)
    6114                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6115                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6116                 :            :                                           "duplicate age actions set");
    6117                 :            :         return 0;
    6118                 :            : }
    6119                 :            : 
    6120                 :            : /**
    6121                 :            :  * Validate the modify-header IPv4 DSCP actions.
    6122                 :            :  *
    6123                 :            :  * @param[in] action_flags
    6124                 :            :  *   Holds the actions detected until now.
    6125                 :            :  * @param[in] action
    6126                 :            :  *   Pointer to the modify action.
    6127                 :            :  * @param[in] item_flags
    6128                 :            :  *   Holds the items detected.
    6129                 :            :  * @param[out] error
    6130                 :            :  *   Pointer to error structure.
    6131                 :            :  *
    6132                 :            :  * @return
    6133                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6134                 :            :  */
    6135                 :            : static int
    6136                 :          0 : flow_dv_validate_action_modify_ipv4_dscp(const uint64_t action_flags,
    6137                 :            :                                          const struct rte_flow_action *action,
    6138                 :            :                                          const uint64_t item_flags,
    6139                 :            :                                          struct rte_flow_error *error)
    6140                 :            : {
    6141                 :            :         int ret = 0;
    6142                 :            : 
    6143                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    6144         [ #  # ]:          0 :         if (!ret) {
    6145         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV4))
    6146                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6147                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6148                 :            :                                                   NULL,
    6149                 :            :                                                   "no ipv4 item in pattern");
    6150                 :            :         }
    6151                 :            :         return ret;
    6152                 :            : }
    6153                 :            : 
    6154                 :            : /**
    6155                 :            :  * Validate the modify-header IPv6 DSCP actions.
    6156                 :            :  *
    6157                 :            :  * @param[in] action_flags
    6158                 :            :  *   Holds the actions detected until now.
    6159                 :            :  * @param[in] action
    6160                 :            :  *   Pointer to the modify action.
    6161                 :            :  * @param[in] item_flags
    6162                 :            :  *   Holds the items detected.
    6163                 :            :  * @param[out] error
    6164                 :            :  *   Pointer to error structure.
    6165                 :            :  *
    6166                 :            :  * @return
    6167                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6168                 :            :  */
    6169                 :            : static int
    6170                 :          0 : flow_dv_validate_action_modify_ipv6_dscp(const uint64_t action_flags,
    6171                 :            :                                          const struct rte_flow_action *action,
    6172                 :            :                                          const uint64_t item_flags,
    6173                 :            :                                          struct rte_flow_error *error)
    6174                 :            : {
    6175                 :            :         int ret = 0;
    6176                 :            : 
    6177                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    6178         [ #  # ]:          0 :         if (!ret) {
    6179         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV6))
    6180                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6181                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6182                 :            :                                                   NULL,
    6183                 :            :                                                   "no ipv6 item in pattern");
    6184                 :            :         }
    6185                 :            :         return ret;
    6186                 :            : }
    6187                 :            : 
    6188                 :            : int
    6189                 :          0 : flow_modify_match_cb(void *tool_ctx __rte_unused,
    6190                 :            :                         struct mlx5_list_entry *entry, void *cb_ctx)
    6191                 :            : {
    6192                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6193                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6194                 :            :         struct mlx5_flow_dv_modify_hdr_resource *resource =
    6195                 :            :                                   container_of(entry, typeof(*resource), entry);
    6196                 :            :         uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type);
    6197                 :            : 
    6198                 :          0 :         key_len += ref->actions_num * sizeof(ref->actions[0]);
    6199         [ #  # ]:          0 :         return ref->actions_num != resource->actions_num ||
    6200         [ #  # ]:          0 :                memcmp(&ref->ft_type, &resource->ft_type, key_len);
    6201                 :            : }
    6202                 :            : 
    6203                 :            : static struct mlx5_indexed_pool *
    6204                 :          0 : flow_dv_modify_ipool_get(struct mlx5_dev_ctx_shared *sh, uint8_t index)
    6205                 :            : {
    6206                 :          0 :         struct mlx5_indexed_pool *ipool = rte_atomic_load_explicit
    6207                 :            :                                      (&sh->mdh_ipools[index], rte_memory_order_seq_cst);
    6208                 :            : 
    6209         [ #  # ]:          0 :         if (!ipool) {
    6210                 :            :                 struct mlx5_indexed_pool *expected = NULL;
    6211                 :          0 :                 struct mlx5_indexed_pool_config cfg =
    6212                 :            :                     (struct mlx5_indexed_pool_config) {
    6213                 :          0 :                        .size = sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
    6214                 :          0 :                                                                    (index + 1) *
    6215                 :            :                                            sizeof(struct mlx5_modification_cmd),
    6216                 :            :                        .trunk_size = 64,
    6217                 :            :                        .grow_trunk = 3,
    6218                 :            :                        .grow_shift = 2,
    6219                 :            :                        .need_lock = 1,
    6220                 :          0 :                        .release_mem_en = !!sh->config.reclaim_mode,
    6221                 :            :                        .per_core_cache =
    6222         [ #  # ]:          0 :                                        sh->config.reclaim_mode ? 0 : (1 << 16),
    6223                 :            :                        .malloc = mlx5_malloc,
    6224                 :            :                        .free = mlx5_free,
    6225                 :            :                        .type = "mlx5_modify_action_resource",
    6226                 :            :                 };
    6227                 :            : 
    6228                 :          0 :                 cfg.size = RTE_ALIGN(cfg.size, sizeof(ipool));
    6229                 :          0 :                 ipool = mlx5_ipool_create(&cfg);
    6230         [ #  # ]:          0 :                 if (!ipool)
    6231                 :          0 :                         return NULL;
    6232         [ #  # ]:          0 :                 if (!rte_atomic_compare_exchange_strong_explicit(&sh->mdh_ipools[index],
    6233                 :            :                                                  &expected, ipool,
    6234                 :            :                                                  rte_memory_order_seq_cst,
    6235                 :            :                                                  rte_memory_order_seq_cst)) {
    6236                 :          0 :                         mlx5_ipool_destroy(ipool);
    6237                 :          0 :                         ipool = rte_atomic_load_explicit(&sh->mdh_ipools[index],
    6238                 :            :                                                 rte_memory_order_seq_cst);
    6239                 :            :                 }
    6240                 :            :         }
    6241                 :            :         return ipool;
    6242                 :            : }
    6243                 :            : 
    6244                 :            : struct mlx5_list_entry *
    6245                 :          0 : flow_modify_create_cb(void *tool_ctx, void *cb_ctx)
    6246                 :            : {
    6247                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6248                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6249                 :            :         struct mlx5dv_dr_domain *ns;
    6250                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry;
    6251                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6252                 :          0 :         struct mlx5_indexed_pool *ipool = flow_dv_modify_ipool_get(sh,
    6253                 :          0 :                                                           ref->actions_num - 1);
    6254                 :            :         int ret = 0;
    6255                 :          0 :         uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]);
    6256                 :            :         uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type);
    6257                 :            :         uint32_t idx;
    6258                 :            : 
    6259         [ #  # ]:          0 :         if (unlikely(!ipool)) {
    6260                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6261                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6262                 :            :                                    NULL, "cannot allocate modify ipool");
    6263                 :          0 :                 return NULL;
    6264                 :            :         }
    6265                 :          0 :         entry = mlx5_ipool_zmalloc(ipool, &idx);
    6266         [ #  # ]:          0 :         if (!entry) {
    6267                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6268                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6269                 :            :                                    "cannot allocate resource memory");
    6270                 :          0 :                 return NULL;
    6271                 :            :         }
    6272                 :          0 :         rte_memcpy(&entry->ft_type,
    6273                 :          0 :                         RTE_PTR_ADD(ref, offsetof(typeof(*ref), ft_type)),
    6274         [ #  # ]:          0 :                         key_len + data_len);
    6275         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2) {
    6276                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    6277                 :          0 :                 struct mlx5dr_action_mh_pattern pattern = {
    6278                 :            :                         .sz = data_len,
    6279                 :          0 :                         .data = (__be64 *)ref->actions
    6280                 :            :                 };
    6281                 :          0 :                 entry->action = mlx5dr_action_create_modify_header(ctx->data2,
    6282                 :            :                         1,
    6283                 :          0 :                         &pattern, 0, ref->flags);
    6284         [ #  # ]:          0 :                 if (!entry->action)
    6285                 :            :                         ret = -1;
    6286                 :            : #else
    6287                 :            :                 ret = -1;
    6288                 :            : #endif
    6289                 :            :         } else {
    6290         [ #  # ]:          0 :                 if (entry->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    6291                 :          0 :                         ns = sh->fdb_domain;
    6292         [ #  # ]:          0 :                 else if (entry->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX)
    6293                 :          0 :                         ns = sh->tx_domain;
    6294                 :            :                 else
    6295                 :          0 :                         ns = sh->rx_domain;
    6296                 :          0 :                 ret = mlx5_flow_os_create_flow_action_modify_header
    6297                 :          0 :                                                 (sh->cdev->ctx, ns, entry,
    6298                 :            :                                                 data_len, &entry->action);
    6299                 :            :         }
    6300                 :            :         if (ret) {
    6301                 :          0 :                 mlx5_ipool_free(sh->mdh_ipools[ref->actions_num - 1], idx);
    6302                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6303                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6304                 :            :                                    NULL, "cannot create modification action");
    6305                 :          0 :                 return NULL;
    6306                 :            :         }
    6307                 :          0 :         entry->idx = idx;
    6308                 :          0 :         return &entry->entry;
    6309                 :            : }
    6310                 :            : 
    6311                 :            : struct mlx5_list_entry *
    6312                 :          0 : flow_modify_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
    6313                 :            :                         void *cb_ctx)
    6314                 :            : {
    6315                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6316                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6317                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry;
    6318                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6319                 :          0 :         uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]);
    6320                 :            :         uint32_t idx;
    6321                 :            : 
    6322                 :          0 :         entry = mlx5_ipool_malloc(sh->mdh_ipools[ref->actions_num - 1],
    6323                 :            :                                   &idx);
    6324         [ #  # ]:          0 :         if (!entry) {
    6325                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6326                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6327                 :            :                                    "cannot allocate resource memory");
    6328                 :          0 :                 return NULL;
    6329                 :            :         }
    6330                 :          0 :         memcpy(entry, oentry, sizeof(*entry) + data_len);
    6331                 :          0 :         entry->idx = idx;
    6332                 :          0 :         return &entry->entry;
    6333                 :            : }
    6334                 :            : 
    6335                 :            : void
    6336                 :          0 : flow_modify_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    6337                 :            : {
    6338                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6339                 :            :         struct mlx5_flow_dv_modify_hdr_resource *res =
    6340                 :            :                 container_of(entry, typeof(*res), entry);
    6341                 :            : 
    6342                 :          0 :         mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
    6343                 :          0 : }
    6344                 :            : 
    6345                 :            : /**
    6346                 :            :  * Validate the sample action.
    6347                 :            :  *
    6348                 :            :  * @param[in, out] action_flags
    6349                 :            :  *   Holds the actions detected until now.
    6350                 :            :  * @param[in] action
    6351                 :            :  *   Pointer to the sample action.
    6352                 :            :  * @param[in] dev
    6353                 :            :  *   Pointer to the Ethernet device structure.
    6354                 :            :  * @param[in] attr
    6355                 :            :  *   Attributes of flow that includes this action.
    6356                 :            :  * @param[in] item_flags
    6357                 :            :  *   Holds the items detected.
    6358                 :            :  * @param[in] rss
    6359                 :            :  *   Pointer to the RSS action.
    6360                 :            :  * @param[out] sample_rss
    6361                 :            :  *   Pointer to the RSS action in sample action list.
    6362                 :            :  * @param[out] count
    6363                 :            :  *   Pointer to the COUNT action in sample action list.
    6364                 :            :  * @param[out] fdb_mirror
    6365                 :            :  *   Pointer to the FDB mirror flag.
    6366                 :            :  * @param root
    6367                 :            :  *   Whether action is on root table.
    6368                 :            :  * @param[out] error
    6369                 :            :  *   Pointer to error structure.
    6370                 :            :  *
    6371                 :            :  * @return
    6372                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6373                 :            :  */
    6374                 :            : static int
    6375                 :          0 : flow_dv_validate_action_sample(uint64_t *action_flags,
    6376                 :            :                                uint64_t *sub_action_flags,
    6377                 :            :                                const struct rte_flow_action *action,
    6378                 :            :                                struct rte_eth_dev *dev,
    6379                 :            :                                const struct rte_flow_attr *attr,
    6380                 :            :                                uint64_t item_flags,
    6381                 :            :                                const struct rte_flow_action_rss *rss,
    6382                 :            :                                const struct rte_flow_action_rss **sample_rss,
    6383                 :            :                                const struct rte_flow_action_count **count,
    6384                 :            :                                int *fdb_mirror,
    6385                 :            :                                uint16_t *sample_port_id,
    6386                 :            :                                bool root,
    6387                 :            :                                struct rte_flow_error *error)
    6388                 :            : {
    6389                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6390                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
    6391                 :          0 :         const struct rte_flow_action_sample *sample = action->conf;
    6392                 :            :         const struct rte_flow_action_port_id *port = NULL;
    6393                 :            :         const struct rte_flow_action *act;
    6394                 :            :         uint16_t queue_index = 0xFFFF;
    6395                 :          0 :         int actions_n = 0;
    6396                 :            :         int ret;
    6397                 :            : 
    6398         [ #  # ]:          0 :         if (!sample)
    6399                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6400                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6401                 :            :                                           "configuration cannot be NULL");
    6402         [ #  # ]:          0 :         if (sample->ratio == 0)
    6403                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6404                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6405                 :            :                                           "ratio value starts from 1");
    6406         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx ||
    6407         [ #  # ]:          0 :             (sample->ratio > 0 && !priv->sampler_en))
    6408                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6409                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6410                 :            :                                           NULL,
    6411                 :            :                                           "sample action not supported");
    6412         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_SAMPLE)
    6413                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6414                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6415                 :            :                                           "Multiple sample actions not "
    6416                 :            :                                           "supported");
    6417         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_METER)
    6418                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6419                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6420                 :            :                                           "wrong action order, meter should "
    6421                 :            :                                           "be after sample action");
    6422         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_JUMP)
    6423                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6424                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6425                 :            :                                           "wrong action order, jump should "
    6426                 :            :                                           "be after sample action");
    6427         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_CT)
    6428                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6429                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6430                 :            :                                           "Sample after CT not supported");
    6431                 :          0 :         act = sample->actions;
    6432         [ #  # ]:          0 :         for (; act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
    6433         [ #  # ]:          0 :                 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
    6434                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6435                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6436                 :            :                                                   act, "too many actions");
    6437   [ #  #  #  #  :          0 :                 switch (act->type) {
             #  #  #  # ]
    6438                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    6439                 :          0 :                         ret = mlx5_flow_validate_action_queue(act,
    6440                 :            :                                                               *sub_action_flags,
    6441                 :            :                                                               dev,
    6442                 :            :                                                               attr, error);
    6443         [ #  # ]:          0 :                         if (ret < 0)
    6444                 :          0 :                                 return ret;
    6445                 :          0 :                         queue_index = ((const struct rte_flow_action_queue *)
    6446                 :          0 :                                                         (act->conf))->index;
    6447                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_QUEUE;
    6448                 :          0 :                         ++actions_n;
    6449                 :          0 :                         break;
    6450                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    6451                 :          0 :                         *sample_rss = act->conf;
    6452                 :          0 :                         ret = mlx5_flow_validate_action_rss(act,
    6453                 :            :                                                             *sub_action_flags,
    6454                 :            :                                                             dev, attr,
    6455                 :            :                                                             item_flags,
    6456                 :            :                                                             error);
    6457         [ #  # ]:          0 :                         if (ret < 0)
    6458                 :          0 :                                 return ret;
    6459   [ #  #  #  # ]:          0 :                         if (rss && *sample_rss &&
    6460         [ #  # ]:          0 :                             ((*sample_rss)->level != rss->level ||
    6461         [ #  # ]:          0 :                             (*sample_rss)->types != rss->types))
    6462                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    6463                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    6464                 :            :                                         NULL,
    6465                 :            :                                         "Can't use the different RSS types "
    6466                 :            :                                         "or level in the same flow");
    6467   [ #  #  #  # ]:          0 :                         if (*sample_rss != NULL && (*sample_rss)->queue_num)
    6468                 :          0 :                                 queue_index = (*sample_rss)->queue[0];
    6469                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_RSS;
    6470                 :          0 :                         ++actions_n;
    6471                 :          0 :                         break;
    6472                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    6473                 :          0 :                         ret = flow_dv_validate_action_mark(dev, act,
    6474                 :            :                                                            *sub_action_flags,
    6475                 :            :                                                            attr, error);
    6476         [ #  # ]:          0 :                         if (ret < 0)
    6477                 :          0 :                                 return ret;
    6478         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY)
    6479                 :          0 :                                 *sub_action_flags |= MLX5_FLOW_ACTION_MARK |
    6480                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    6481                 :            :                         else
    6482                 :          0 :                                 *sub_action_flags |= MLX5_FLOW_ACTION_MARK;
    6483                 :          0 :                         ++actions_n;
    6484                 :          0 :                         break;
    6485                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    6486                 :          0 :                         ret = flow_dv_validate_action_count
    6487                 :          0 :                                 (dev, false, *action_flags | *sub_action_flags,
    6488                 :            :                                  root, error);
    6489         [ #  # ]:          0 :                         if (ret < 0)
    6490                 :          0 :                                 return ret;
    6491                 :          0 :                         *count = act->conf;
    6492                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_COUNT;
    6493                 :          0 :                         *action_flags |= MLX5_FLOW_ACTION_COUNT;
    6494                 :          0 :                         ++actions_n;
    6495                 :          0 :                         break;
    6496                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
    6497                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    6498                 :          0 :                         ret = flow_dv_validate_action_port_id(dev,
    6499                 :            :                                                               *sub_action_flags,
    6500                 :            :                                                               act,
    6501                 :            :                                                               attr,
    6502                 :            :                                                               error);
    6503         [ #  # ]:          0 :                         if (ret)
    6504                 :          0 :                                 return ret;
    6505         [ #  # ]:          0 :                         if (act->type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
    6506                 :          0 :                                 port = (const struct rte_flow_action_port_id *)
    6507                 :            :                                         act->conf;
    6508         [ #  # ]:          0 :                                 *sample_port_id = port->original ?
    6509                 :          0 :                                                   dev->data->port_id : port->id;
    6510                 :            :                         } else {
    6511                 :          0 :                                 *sample_port_id = ((const struct rte_flow_action_ethdev *)
    6512                 :          0 :                                                   act->conf)->port_id;
    6513                 :            :                         }
    6514                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_PORT_ID;
    6515                 :          0 :                         ++actions_n;
    6516                 :          0 :                         break;
    6517                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    6518                 :          0 :                         ret = mlx5_flow_dv_validate_action_raw_encap_decap
    6519                 :          0 :                                 (dev, NULL, act->conf, attr, sub_action_flags,
    6520                 :            :                                  &actions_n, action, item_flags, error);
    6521         [ #  # ]:          0 :                         if (ret < 0)
    6522                 :          0 :                                 return ret;
    6523                 :          0 :                         ++actions_n;
    6524                 :          0 :                         break;
    6525                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    6526                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    6527                 :          0 :                         ret = mlx5_flow_dv_validate_action_l2_encap(dev,
    6528                 :            :                                                                     *sub_action_flags,
    6529                 :            :                                                                     act, attr,
    6530                 :            :                                                                     error);
    6531         [ #  # ]:          0 :                         if (ret < 0)
    6532                 :          0 :                                 return ret;
    6533                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_ENCAP;
    6534                 :          0 :                         ++actions_n;
    6535                 :          0 :                         break;
    6536                 :          0 :                 default:
    6537                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6538                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6539                 :            :                                                   NULL,
    6540                 :            :                                                   "Doesn't support optional "
    6541                 :            :                                                   "action");
    6542                 :            :                 }
    6543                 :            :         }
    6544         [ #  # ]:          0 :         if (attr->ingress) {
    6545         [ #  # ]:          0 :                 if (!(*sub_action_flags & (MLX5_FLOW_ACTION_QUEUE |
    6546                 :            :                                           MLX5_FLOW_ACTION_RSS)))
    6547                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6548                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6549                 :            :                                                   NULL,
    6550                 :            :                                                   "Ingress must has a dest "
    6551                 :            :                                                   "QUEUE for Sample");
    6552         [ #  # ]:          0 :         } else if (attr->egress) {
    6553                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6554                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    6555                 :            :                                           NULL,
    6556                 :            :                                           "Sample Only support Ingress "
    6557                 :            :                                           "or E-Switch");
    6558         [ #  # ]:          0 :         } else if (sample->actions->type != RTE_FLOW_ACTION_TYPE_END) {
    6559                 :            :                 MLX5_ASSERT(attr->transfer);
    6560         [ #  # ]:          0 :                 if (sample->ratio > 1)
    6561                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6562                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6563                 :            :                                                   NULL,
    6564                 :            :                                                   "E-Switch doesn't support "
    6565                 :            :                                                   "any optional action "
    6566                 :            :                                                   "for sampling");
    6567         [ #  # ]:          0 :                 if (*sub_action_flags & MLX5_FLOW_ACTION_QUEUE)
    6568                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6569                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6570                 :            :                                                   NULL,
    6571                 :            :                                                   "unsupported action QUEUE");
    6572         [ #  # ]:          0 :                 if (*sub_action_flags & MLX5_FLOW_ACTION_RSS)
    6573                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6574                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6575                 :            :                                                   NULL,
    6576                 :            :                                                   "unsupported action QUEUE");
    6577         [ #  # ]:          0 :                 if (!(*sub_action_flags & MLX5_FLOW_ACTION_PORT_ID))
    6578                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6579                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6580                 :            :                                                   NULL,
    6581                 :            :                                                   "E-Switch must has a dest "
    6582                 :            :                                                   "port for mirroring");
    6583                 :          0 :                 *fdb_mirror = 1;
    6584                 :            :         }
    6585                 :            :         /* Continue validation for Xcap actions.*/
    6586   [ #  #  #  # ]:          0 :         if ((*sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) &&
    6587         [ #  # ]:          0 :             (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index))) {
    6588         [ #  # ]:          0 :                 if ((*sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
    6589                 :            :                      MLX5_FLOW_XCAP_ACTIONS)
    6590                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6591                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6592                 :            :                                                   NULL, "encap and decap "
    6593                 :            :                                                   "combination aren't "
    6594                 :            :                                                   "supported");
    6595   [ #  #  #  # ]:          0 :                 if (attr->ingress && (*sub_action_flags & MLX5_FLOW_ACTION_ENCAP))
    6596                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6597                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6598                 :            :                                                   NULL, "encap is not supported"
    6599                 :            :                                                   " for ingress traffic");
    6600                 :            :         }
    6601                 :            :         return 0;
    6602                 :            : }
    6603                 :            : 
    6604                 :            : int
    6605                 :          0 : __flow_modify_hdr_resource_register(struct rte_eth_dev *dev,
    6606                 :            :                         struct mlx5_flow_dv_modify_hdr_resource *resource,
    6607                 :            :                         struct mlx5_flow_dv_modify_hdr_resource **modify,
    6608                 :            :                         struct rte_flow_error *error)
    6609                 :            : {
    6610                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6611                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
    6612                 :          0 :         uint32_t key_len = sizeof(*resource) -
    6613                 :            :                            offsetof(typeof(*resource), ft_type) +
    6614                 :          0 :                            resource->actions_num * sizeof(resource->actions[0]);
    6615                 :            :         struct mlx5_list_entry *entry;
    6616                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    6617                 :            :                 .error = error,
    6618                 :            :                 .data = resource,
    6619                 :          0 :                 .data2 = priv->dr_ctx,
    6620                 :            :         };
    6621                 :            :         struct mlx5_hlist *modify_cmds;
    6622                 :            :         uint64_t key64;
    6623                 :            : 
    6624                 :          0 :         modify_cmds = flow_dv_hlist_prepare(sh, &sh->modify_cmds,
    6625                 :            :                                 "hdr_modify",
    6626                 :            :                                 MLX5_FLOW_HDR_MODIFY_HTABLE_SZ,
    6627                 :            :                                 true, false, sh,
    6628                 :            :                                 flow_modify_create_cb,
    6629                 :            :                                 flow_modify_match_cb,
    6630                 :            :                                 flow_modify_remove_cb,
    6631                 :            :                                 flow_modify_clone_cb,
    6632                 :            :                                 flow_modify_clone_free_cb,
    6633                 :            :                                 error);
    6634         [ #  # ]:          0 :         if (unlikely(!modify_cmds))
    6635                 :          0 :                 return -rte_errno;
    6636         [ #  # ]:          0 :         if (resource->actions_num > flow_dv_modify_hdr_action_max(dev,
    6637         [ #  # ]:          0 :                                                                 resource->root))
    6638                 :          0 :                 return rte_flow_error_set(error, EOVERFLOW,
    6639                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6640                 :            :                                           "too many modify header items");
    6641                 :          0 :         key64 = __rte_raw_cksum(&resource->ft_type, key_len, 0);
    6642                 :          0 :         entry = mlx5_hlist_register(modify_cmds, key64, &ctx);
    6643         [ #  # ]:          0 :         if (!entry)
    6644                 :          0 :                 return -rte_errno;
    6645                 :          0 :         *modify = container_of(entry, typeof(*resource), entry);
    6646                 :          0 :         return 0;
    6647                 :            : }
    6648                 :            : 
    6649                 :            : /**
    6650                 :            :  * Find existing modify-header resource or create and register a new one.
    6651                 :            :  *
    6652                 :            :  * @param dev[in, out]
    6653                 :            :  *   Pointer to rte_eth_dev structure.
    6654                 :            :  * @param[in, out] resource
    6655                 :            :  *   Pointer to modify-header resource.
    6656                 :            :  * @param[in, out] dev_flow
    6657                 :            :  *   Pointer to the dev_flow.
    6658                 :            :  * @param[out] error
    6659                 :            :  *   pointer to error structure.
    6660                 :            :  *
    6661                 :            :  * @return
    6662                 :            :  *   0 on success otherwise -errno and errno is set.
    6663                 :            :  */
    6664                 :            : static int
    6665                 :            : flow_dv_modify_hdr_resource_register
    6666                 :            :                         (struct rte_eth_dev *dev,
    6667                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    6668                 :            :                          struct mlx5_flow *dev_flow,
    6669                 :            :                          struct rte_flow_error *error)
    6670                 :            : {
    6671                 :          0 :         resource->root = !dev_flow->dv.group;
    6672                 :          0 :         return __flow_modify_hdr_resource_register(dev, resource,
    6673                 :          0 :                 &dev_flow->handle->dvh.modify_hdr, error);
    6674                 :            : }
    6675                 :            : 
    6676                 :            : /**
    6677                 :            :  * Get DV flow counter by index.
    6678                 :            :  *
    6679                 :            :  * @param[in] dev
    6680                 :            :  *   Pointer to the Ethernet device structure.
    6681                 :            :  * @param[in] idx
    6682                 :            :  *   mlx5 flow counter index in the container.
    6683                 :            :  * @param[out] ppool
    6684                 :            :  *   mlx5 flow counter pool in the container.
    6685                 :            :  *
    6686                 :            :  * @return
    6687                 :            :  *   Pointer to the counter, NULL otherwise.
    6688                 :            :  */
    6689                 :            : static struct mlx5_flow_counter *
    6690                 :            : flow_dv_counter_get_by_idx(struct rte_eth_dev *dev,
    6691                 :            :                            uint32_t idx,
    6692                 :            :                            struct mlx5_flow_counter_pool **ppool)
    6693                 :            : {
    6694                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6695                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6696                 :            :         struct mlx5_flow_counter_pool *pool;
    6697                 :            : 
    6698                 :            :         /* Decrease to original index and clear shared bit. */
    6699                 :          0 :         idx = (idx - 1) & (MLX5_CNT_SHARED_OFFSET - 1);
    6700                 :            :         MLX5_ASSERT(idx / MLX5_COUNTERS_PER_POOL < MLX5_COUNTER_POOLS_MAX_NUM);
    6701                 :          0 :         pool = cmng->pools[idx / MLX5_COUNTERS_PER_POOL];
    6702                 :            :         MLX5_ASSERT(pool);
    6703                 :            :         if (ppool)
    6704                 :            :                 *ppool = pool;
    6705   [ #  #  #  #  :          0 :         return MLX5_POOL_GET_CNT(pool, idx % MLX5_COUNTERS_PER_POOL);
          #  #  #  #  #  
                #  #  # ]
    6706                 :            : }
    6707                 :            : 
    6708                 :            : /**
    6709                 :            :  * Check the devx counter belongs to the pool.
    6710                 :            :  *
    6711                 :            :  * @param[in] pool
    6712                 :            :  *   Pointer to the counter pool.
    6713                 :            :  * @param[in] id
    6714                 :            :  *   The counter devx ID.
    6715                 :            :  *
    6716                 :            :  * @return
    6717                 :            :  *   True if counter belongs to the pool, false otherwise.
    6718                 :            :  */
    6719                 :            : static bool
    6720                 :            : flow_dv_is_counter_in_pool(struct mlx5_flow_counter_pool *pool, int id)
    6721                 :            : {
    6722                 :          0 :         int base = (pool->min_dcs->id / MLX5_COUNTERS_PER_POOL) *
    6723                 :            :                    MLX5_COUNTERS_PER_POOL;
    6724                 :            : 
    6725   [ #  #  #  # ]:          0 :         if (id >= base && id < base + MLX5_COUNTERS_PER_POOL)
    6726                 :            :                 return true;
    6727                 :            :         return false;
    6728                 :            : }
    6729                 :            : 
    6730                 :            : /**
    6731                 :            :  * Get a pool by devx counter ID.
    6732                 :            :  *
    6733                 :            :  * @param[in] cmng
    6734                 :            :  *   Pointer to the counter management.
    6735                 :            :  * @param[in] id
    6736                 :            :  *   The counter devx ID.
    6737                 :            :  *
    6738                 :            :  * @return
    6739                 :            :  *   The counter pool pointer if exists, NULL otherwise,
    6740                 :            :  */
    6741                 :            : static struct mlx5_flow_counter_pool *
    6742                 :          0 : flow_dv_find_pool_by_id(struct mlx5_flow_counter_mng *cmng, int id)
    6743                 :            : {
    6744                 :            :         uint32_t i;
    6745                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6746                 :            : 
    6747                 :          0 :         rte_spinlock_lock(&cmng->pool_update_sl);
    6748                 :            :         /* Check last used pool. */
    6749         [ #  # ]:          0 :         if (cmng->last_pool_idx != POOL_IDX_INVALID &&
    6750         [ #  # ]:          0 :             flow_dv_is_counter_in_pool(cmng->pools[cmng->last_pool_idx], id)) {
    6751                 :            :                 pool = cmng->pools[cmng->last_pool_idx];
    6752                 :          0 :                 goto out;
    6753                 :            :         }
    6754                 :            :         /* ID out of range means no suitable pool in the container. */
    6755   [ #  #  #  # ]:          0 :         if (id > cmng->max_id || id < cmng->min_id)
    6756                 :          0 :                 goto out;
    6757                 :            :         /*
    6758                 :            :          * Find the pool from the end of the container, since mostly counter
    6759                 :            :          * ID is sequence increasing, and the last pool should be the needed
    6760                 :            :          * one.
    6761                 :            :          */
    6762                 :          0 :         i = cmng->n_valid;
    6763         [ #  # ]:          0 :         while (i--) {
    6764         [ #  # ]:          0 :                 struct mlx5_flow_counter_pool *pool_tmp = cmng->pools[i];
    6765                 :            : 
    6766                 :            :                 if (flow_dv_is_counter_in_pool(pool_tmp, id)) {
    6767                 :            :                         pool = pool_tmp;
    6768                 :            :                         break;
    6769                 :            :                 }
    6770                 :            :         }
    6771                 :          0 : out:
    6772                 :            :         rte_spinlock_unlock(&cmng->pool_update_sl);
    6773                 :          0 :         return pool;
    6774                 :            : }
    6775                 :            : 
    6776                 :            : /**
    6777                 :            :  * Query a devx flow counter.
    6778                 :            :  *
    6779                 :            :  * @param[in] dev
    6780                 :            :  *   Pointer to the Ethernet device structure.
    6781                 :            :  * @param[in] counter
    6782                 :            :  *   Index to the flow counter.
    6783                 :            :  * @param[out] pkts
    6784                 :            :  *   The statistics value of packets.
    6785                 :            :  * @param[out] bytes
    6786                 :            :  *   The statistics value of bytes.
    6787                 :            :  *
    6788                 :            :  * @return
    6789                 :            :  *   0 on success, otherwise a negative errno value and rte_errno is set.
    6790                 :            :  */
    6791                 :            : static inline int
    6792                 :          0 : _flow_dv_query_count(struct rte_eth_dev *dev, uint32_t counter, uint64_t *pkts,
    6793                 :            :                      uint64_t *bytes)
    6794                 :            : {
    6795         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6796                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6797                 :            :         struct mlx5_flow_counter *cnt;
    6798                 :            :         int offset;
    6799                 :            : 
    6800                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, &pool);
    6801                 :            :         MLX5_ASSERT(pool);
    6802         [ #  # ]:          0 :         if (priv->sh->sws_cmng.counter_fallback)
    6803                 :          0 :                 return mlx5_devx_cmd_flow_counter_query(cnt->dcs_when_active, 0,
    6804                 :            :                                         0, pkts, bytes, 0, NULL, NULL, 0);
    6805                 :          0 :         rte_spinlock_lock(&pool->sl);
    6806         [ #  # ]:          0 :         if (!pool->raw) {
    6807                 :          0 :                 *pkts = 0;
    6808                 :          0 :                 *bytes = 0;
    6809                 :            :         } else {
    6810         [ #  # ]:          0 :                 offset = MLX5_CNT_ARRAY_IDX(pool, cnt);
    6811                 :          0 :                 *pkts = rte_be_to_cpu_64(pool->raw->data[offset].hits);
    6812                 :          0 :                 *bytes = rte_be_to_cpu_64(pool->raw->data[offset].bytes);
    6813                 :            :         }
    6814                 :            :         rte_spinlock_unlock(&pool->sl);
    6815                 :          0 :         return 0;
    6816                 :            : }
    6817                 :            : 
    6818                 :            : /**
    6819                 :            :  * Create and initialize a new counter pool.
    6820                 :            :  *
    6821                 :            :  * @param[in] dev
    6822                 :            :  *   Pointer to the Ethernet device structure.
    6823                 :            :  * @param[out] dcs
    6824                 :            :  *   The devX counter handle.
    6825                 :            :  * @param[in] age
    6826                 :            :  *   Whether the pool is for counter that was allocated for aging.
    6827                 :            :  *
    6828                 :            :  * @return
    6829                 :            :  *   The pool container pointer on success, NULL otherwise and rte_errno is set.
    6830                 :            :  */
    6831                 :            : static struct mlx5_flow_counter_pool *
    6832                 :          0 : flow_dv_pool_create(struct rte_eth_dev *dev, struct mlx5_devx_obj *dcs,
    6833                 :            :                     uint32_t age)
    6834                 :            : {
    6835                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6836                 :            :         struct mlx5_flow_counter_pool *pool;
    6837                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6838                 :          0 :         bool fallback = cmng->counter_fallback;
    6839                 :            :         uint32_t size = sizeof(*pool);
    6840                 :            : 
    6841         [ #  # ]:          0 :         if (cmng->n_valid == MLX5_COUNTER_POOLS_MAX_NUM) {
    6842                 :          0 :                 DRV_LOG(ERR, "All counter is in used, try again later.");
    6843                 :          0 :                 rte_errno = EAGAIN;
    6844                 :          0 :                 return NULL;
    6845                 :            :         }
    6846                 :            :         size += MLX5_COUNTERS_PER_POOL * MLX5_CNT_SIZE;
    6847         [ #  # ]:          0 :         size += (!age ? 0 : MLX5_COUNTERS_PER_POOL * MLX5_AGE_SIZE);
    6848                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, size, 0, SOCKET_ID_ANY);
    6849         [ #  # ]:          0 :         if (!pool) {
    6850                 :          0 :                 rte_errno = ENOMEM;
    6851                 :          0 :                 return NULL;
    6852                 :            :         }
    6853                 :          0 :         pool->raw = NULL;
    6854                 :          0 :         pool->is_aged = !!age;
    6855                 :          0 :         pool->query_gen = 0;
    6856                 :          0 :         pool->min_dcs = dcs;
    6857                 :            :         rte_spinlock_init(&pool->sl);
    6858                 :            :         rte_spinlock_init(&pool->csl);
    6859                 :          0 :         TAILQ_INIT(&pool->counters[0]);
    6860                 :          0 :         TAILQ_INIT(&pool->counters[1]);
    6861                 :          0 :         pool->time_of_last_age_check = MLX5_CURR_TIME_SEC;
    6862                 :          0 :         rte_spinlock_lock(&cmng->pool_update_sl);
    6863                 :          0 :         pool->index = cmng->n_valid;
    6864                 :          0 :         cmng->pools[pool->index] = pool;
    6865                 :          0 :         cmng->n_valid++;
    6866         [ #  # ]:          0 :         if (unlikely(fallback)) {
    6867                 :          0 :                 int base = RTE_ALIGN_FLOOR(dcs->id, MLX5_COUNTERS_PER_POOL);
    6868                 :            : 
    6869         [ #  # ]:          0 :                 if (base < cmng->min_id)
    6870                 :          0 :                         cmng->min_id = base;
    6871         [ #  # ]:          0 :                 if (base > cmng->max_id)
    6872                 :          0 :                         cmng->max_id = base + MLX5_COUNTERS_PER_POOL - 1;
    6873                 :          0 :                 cmng->last_pool_idx = pool->index;
    6874                 :            :         }
    6875                 :            :         rte_spinlock_unlock(&cmng->pool_update_sl);
    6876                 :          0 :         return pool;
    6877                 :            : }
    6878                 :            : 
    6879                 :            : /**
    6880                 :            :  * Prepare a new counter and/or a new counter pool.
    6881                 :            :  *
    6882                 :            :  * @param[in] dev
    6883                 :            :  *   Pointer to the Ethernet device structure.
    6884                 :            :  * @param[out] cnt_free
    6885                 :            :  *   Where to put the pointer of a new counter.
    6886                 :            :  * @param[in] age
    6887                 :            :  *   Whether the pool is for counter that was allocated for aging.
    6888                 :            :  *
    6889                 :            :  * @return
    6890                 :            :  *   The counter pool pointer and @p cnt_free is set on success,
    6891                 :            :  *   NULL otherwise and rte_errno is set.
    6892                 :            :  */
    6893                 :            : static struct mlx5_flow_counter_pool *
    6894                 :          0 : flow_dv_counter_pool_prepare(struct rte_eth_dev *dev,
    6895                 :            :                              struct mlx5_flow_counter **cnt_free,
    6896                 :            :                              uint32_t age)
    6897                 :            : {
    6898                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6899                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6900                 :            :         struct mlx5_flow_counter_pool *pool;
    6901                 :            :         struct mlx5_counters tmp_tq;
    6902                 :            :         struct mlx5_devx_obj *dcs = NULL;
    6903                 :            :         struct mlx5_flow_counter *cnt;
    6904                 :          0 :         enum mlx5_counter_type cnt_type =
    6905                 :          0 :                         age ? MLX5_COUNTER_TYPE_AGE : MLX5_COUNTER_TYPE_ORIGIN;
    6906                 :          0 :         bool fallback = priv->sh->sws_cmng.counter_fallback;
    6907                 :            :         uint32_t i;
    6908                 :            : 
    6909         [ #  # ]:          0 :         if (fallback) {
    6910                 :            :                 /* bulk_bitmap must be 0 for single counter allocation. */
    6911                 :          0 :                 dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0);
    6912         [ #  # ]:          0 :                 if (!dcs)
    6913                 :            :                         return NULL;
    6914                 :          0 :                 pool = flow_dv_find_pool_by_id(cmng, dcs->id);
    6915         [ #  # ]:          0 :                 if (!pool) {
    6916                 :          0 :                         pool = flow_dv_pool_create(dev, dcs, age);
    6917         [ #  # ]:          0 :                         if (!pool) {
    6918                 :          0 :                                 mlx5_devx_cmd_destroy(dcs);
    6919                 :          0 :                                 return NULL;
    6920                 :            :                         }
    6921                 :            :                 }
    6922                 :          0 :                 i = dcs->id % MLX5_COUNTERS_PER_POOL;
    6923         [ #  # ]:          0 :                 cnt = MLX5_POOL_GET_CNT(pool, i);
    6924                 :          0 :                 cnt->pool = pool;
    6925                 :          0 :                 cnt->dcs_when_free = dcs;
    6926                 :          0 :                 *cnt_free = cnt;
    6927                 :          0 :                 return pool;
    6928                 :            :         }
    6929                 :          0 :         dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0x4);
    6930         [ #  # ]:          0 :         if (!dcs) {
    6931                 :          0 :                 rte_errno = ENODATA;
    6932                 :          0 :                 return NULL;
    6933                 :            :         }
    6934                 :          0 :         pool = flow_dv_pool_create(dev, dcs, age);
    6935         [ #  # ]:          0 :         if (!pool) {
    6936                 :          0 :                 mlx5_devx_cmd_destroy(dcs);
    6937                 :          0 :                 return NULL;
    6938                 :            :         }
    6939                 :          0 :         TAILQ_INIT(&tmp_tq);
    6940         [ #  # ]:          0 :         for (i = 1; i < MLX5_COUNTERS_PER_POOL; ++i) {
    6941         [ #  # ]:          0 :                 cnt = MLX5_POOL_GET_CNT(pool, i);
    6942                 :          0 :                 cnt->pool = pool;
    6943         [ #  # ]:          0 :                 TAILQ_INSERT_HEAD(&tmp_tq, cnt, next);
    6944                 :            :         }
    6945                 :          0 :         rte_spinlock_lock(&cmng->csl[cnt_type]);
    6946         [ #  # ]:          0 :         TAILQ_CONCAT(&cmng->counters[cnt_type], &tmp_tq, next);
    6947                 :            :         rte_spinlock_unlock(&cmng->csl[cnt_type]);
    6948                 :          0 :         *cnt_free = MLX5_POOL_GET_CNT(pool, 0);
    6949                 :          0 :         (*cnt_free)->pool = pool;
    6950                 :          0 :         return pool;
    6951                 :            : }
    6952                 :            : 
    6953                 :            : /**
    6954                 :            :  * Allocate a flow counter.
    6955                 :            :  *
    6956                 :            :  * @param[in] dev
    6957                 :            :  *   Pointer to the Ethernet device structure.
    6958                 :            :  * @param[in] age
    6959                 :            :  *   Whether the counter was allocated for aging.
    6960                 :            :  *
    6961                 :            :  * @return
    6962                 :            :  *   Index to flow counter on success, 0 otherwise and rte_errno is set.
    6963                 :            :  */
    6964                 :            : static uint32_t
    6965                 :          0 : flow_dv_counter_alloc(struct rte_eth_dev *dev, uint32_t age)
    6966                 :            : {
    6967                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6968                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6969                 :          0 :         struct mlx5_flow_counter *cnt_free = NULL;
    6970                 :          0 :         bool fallback = priv->sh->sws_cmng.counter_fallback;
    6971                 :            :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6972                 :          0 :         enum mlx5_counter_type cnt_type =
    6973                 :          0 :                         age ? MLX5_COUNTER_TYPE_AGE : MLX5_COUNTER_TYPE_ORIGIN;
    6974                 :            :         uint32_t cnt_idx;
    6975                 :            : 
    6976         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
    6977                 :          0 :                 rte_errno = ENOTSUP;
    6978                 :          0 :                 return 0;
    6979                 :            :         }
    6980                 :            :         /* Get free counters from container. */
    6981                 :          0 :         rte_spinlock_lock(&cmng->csl[cnt_type]);
    6982                 :          0 :         cnt_free = TAILQ_FIRST(&cmng->counters[cnt_type]);
    6983         [ #  # ]:          0 :         if (cnt_free)
    6984         [ #  # ]:          0 :                 TAILQ_REMOVE(&cmng->counters[cnt_type], cnt_free, next);
    6985                 :            :         rte_spinlock_unlock(&cmng->csl[cnt_type]);
    6986   [ #  #  #  # ]:          0 :         if (!cnt_free && !flow_dv_counter_pool_prepare(dev, &cnt_free, age))
    6987                 :          0 :                 goto err;
    6988                 :          0 :         pool = cnt_free->pool;
    6989         [ #  # ]:          0 :         if (fallback)
    6990                 :          0 :                 cnt_free->dcs_when_active = cnt_free->dcs_when_free;
    6991                 :            :         /* Create a DV counter action only in the first time usage. */
    6992         [ #  # ]:          0 :         if (!cnt_free->action) {
    6993                 :            :                 uint16_t offset;
    6994                 :            :                 struct mlx5_devx_obj *dcs;
    6995                 :            :                 int ret;
    6996                 :            : 
    6997         [ #  # ]:          0 :                 if (!fallback) {
    6998         [ #  # ]:          0 :                         offset = MLX5_CNT_ARRAY_IDX(pool, cnt_free);
    6999                 :          0 :                         dcs = pool->min_dcs;
    7000                 :            :                 } else {
    7001                 :            :                         offset = 0;
    7002                 :          0 :                         dcs = cnt_free->dcs_when_free;
    7003                 :            :                 }
    7004                 :          0 :                 ret = mlx5_flow_os_create_flow_action_count(dcs->obj, offset,
    7005                 :            :                                                             &cnt_free->action);
    7006                 :            :                 if (ret) {
    7007                 :          0 :                         rte_errno = errno;
    7008                 :          0 :                         goto err;
    7009                 :            :                 }
    7010                 :            :         }
    7011         [ #  # ]:          0 :         cnt_idx = MLX5_MAKE_CNT_IDX(pool->index,
    7012                 :            :                                 MLX5_CNT_ARRAY_IDX(pool, cnt_free));
    7013                 :            :         /* Update the counter reset values. */
    7014         [ #  # ]:          0 :         if (_flow_dv_query_count(dev, cnt_idx, &cnt_free->hits,
    7015                 :            :                                  &cnt_free->bytes))
    7016                 :          0 :                 goto err;
    7017   [ #  #  #  # ]:          0 :         if (!fallback && !priv->sh->sws_cmng.query_thread_on)
    7018                 :            :                 /* Start the asynchronous batch query by the host thread. */
    7019                 :          0 :                 mlx5_set_query_alarm(priv->sh);
    7020                 :            :         /*
    7021                 :            :          * When the count action isn't shared (by ID), shared_info field is
    7022                 :            :          * used for indirect action API's refcnt.
    7023                 :            :          * When the counter action is not shared neither by ID nor by indirect
    7024                 :            :          * action API, shared info must be 1.
    7025                 :            :          */
    7026                 :          0 :         cnt_free->shared_info.refcnt = 1;
    7027                 :          0 :         return cnt_idx;
    7028                 :          0 : err:
    7029         [ #  # ]:          0 :         if (cnt_free) {
    7030                 :          0 :                 cnt_free->pool = pool;
    7031         [ #  # ]:          0 :                 if (fallback)
    7032                 :          0 :                         cnt_free->dcs_when_free = cnt_free->dcs_when_active;
    7033                 :            :                 rte_spinlock_lock(&cmng->csl[cnt_type]);
    7034                 :          0 :                 TAILQ_INSERT_TAIL(&cmng->counters[cnt_type], cnt_free, next);
    7035                 :            :                 rte_spinlock_unlock(&cmng->csl[cnt_type]);
    7036                 :            :         }
    7037                 :            :         return 0;
    7038                 :            : }
    7039                 :            : 
    7040                 :            : /**
    7041                 :            :  * Get age param from counter index.
    7042                 :            :  *
    7043                 :            :  * @param[in] dev
    7044                 :            :  *   Pointer to the Ethernet device structure.
    7045                 :            :  * @param[in] counter
    7046                 :            :  *   Index to the counter handler.
    7047                 :            :  *
    7048                 :            :  * @return
    7049                 :            :  *   The aging parameter specified for the counter index.
    7050                 :            :  */
    7051                 :            : static struct mlx5_age_param*
    7052                 :            : flow_dv_counter_idx_get_age(struct rte_eth_dev *dev,
    7053                 :            :                                 uint32_t counter)
    7054                 :            : {
    7055                 :            :         struct mlx5_flow_counter *cnt;
    7056                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    7057                 :            : 
    7058                 :            :         flow_dv_counter_get_by_idx(dev, counter, &pool);
    7059                 :            :         counter = (counter - 1) % MLX5_COUNTERS_PER_POOL;
    7060                 :            :         cnt = MLX5_POOL_GET_CNT(pool, counter);
    7061                 :          0 :         return MLX5_CNT_TO_AGE(cnt);
    7062                 :            : }
    7063                 :            : 
    7064                 :            : /**
    7065                 :            :  * Remove a flow counter from aged counter list.
    7066                 :            :  *
    7067                 :            :  * @param[in] dev
    7068                 :            :  *   Pointer to the Ethernet device structure.
    7069                 :            :  * @param[in] counter
    7070                 :            :  *   Index to the counter handler.
    7071                 :            :  * @param[in] cnt
    7072                 :            :  *   Pointer to the counter handler.
    7073                 :            :  */
    7074                 :            : static void
    7075                 :          0 : flow_dv_counter_remove_from_age(struct rte_eth_dev *dev,
    7076                 :            :                                 uint32_t counter, struct mlx5_flow_counter *cnt)
    7077                 :            : {
    7078                 :            :         struct mlx5_age_info *age_info;
    7079                 :            :         struct mlx5_age_param *age_param;
    7080                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7081                 :            :         uint16_t expected = AGE_CANDIDATE;
    7082                 :            : 
    7083         [ #  # ]:          0 :         age_info = GET_PORT_AGE_INFO(priv);
    7084                 :            :         age_param = flow_dv_counter_idx_get_age(dev, counter);
    7085         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&age_param->state, &expected,
    7086                 :            :                                          AGE_FREE, rte_memory_order_relaxed,
    7087                 :            :                                          rte_memory_order_relaxed)) {
    7088                 :            :                 /**
    7089                 :            :                  * We need the lock even it is age timeout,
    7090                 :            :                  * since counter may still in process.
    7091                 :            :                  */
    7092                 :          0 :                 rte_spinlock_lock(&age_info->aged_sl);
    7093         [ #  # ]:          0 :                 TAILQ_REMOVE(&age_info->aged_counters, cnt, next);
    7094                 :            :                 rte_spinlock_unlock(&age_info->aged_sl);
    7095                 :          0 :                 rte_atomic_store_explicit(&age_param->state, AGE_FREE, rte_memory_order_relaxed);
    7096                 :            :         }
    7097                 :          0 : }
    7098                 :            : 
    7099                 :            : /**
    7100                 :            :  * Release a flow counter.
    7101                 :            :  *
    7102                 :            :  * @param[in] dev
    7103                 :            :  *   Pointer to the Ethernet device structure.
    7104                 :            :  * @param[in] counter
    7105                 :            :  *   Index to the counter handler.
    7106                 :            :  */
    7107                 :            : static void
    7108                 :          0 : flow_dv_counter_free(struct rte_eth_dev *dev, uint32_t counter)
    7109                 :            : {
    7110                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7111                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    7112                 :            :         struct mlx5_flow_counter *cnt;
    7113                 :            :         enum mlx5_counter_type cnt_type;
    7114                 :            : 
    7115         [ #  # ]:          0 :         if (!counter)
    7116                 :            :                 return;
    7117                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, &pool);
    7118                 :            :         MLX5_ASSERT(pool);
    7119         [ #  # ]:          0 :         if (pool->is_aged) {
    7120                 :          0 :                 flow_dv_counter_remove_from_age(dev, counter, cnt);
    7121                 :            :         } else {
    7122                 :            :                 /*
    7123                 :            :                  * If the counter action is shared by indirect action API,
    7124                 :            :                  * the atomic function reduces its references counter.
    7125                 :            :                  * If after the reduction the action is still referenced, the
    7126                 :            :                  * function returns here and does not release it.
    7127                 :            :                  * When the counter action is not shared by
    7128                 :            :                  * indirect action API, shared info is 1 before the reduction,
    7129                 :            :                  * so this condition is failed and function doesn't return here.
    7130                 :            :                  */
    7131         [ #  # ]:          0 :                 if (rte_atomic_fetch_sub_explicit(&cnt->shared_info.refcnt, 1,
    7132                 :            :                                        rte_memory_order_relaxed) - 1)
    7133                 :            :                         return;
    7134                 :            :         }
    7135                 :          0 :         cnt->pool = pool;
    7136                 :            :         /*
    7137                 :            :          * Put the counter back to list to be updated in none fallback mode.
    7138                 :            :          * Currently, we are using two list alternately, while one is in query,
    7139                 :            :          * add the freed counter to the other list based on the pool query_gen
    7140                 :            :          * value. After query finishes, add counter the list to the global
    7141                 :            :          * container counter list. The list changes while query starts. In
    7142                 :            :          * this case, lock will not be needed as query callback and release
    7143                 :            :          * function both operate with the different list.
    7144                 :            :          */
    7145         [ #  # ]:          0 :         if (!priv->sh->sws_cmng.counter_fallback) {
    7146                 :          0 :                 rte_spinlock_lock(&pool->csl);
    7147                 :          0 :                 TAILQ_INSERT_TAIL(&pool->counters[pool->query_gen], cnt, next);
    7148                 :            :                 rte_spinlock_unlock(&pool->csl);
    7149                 :            :         } else {
    7150                 :          0 :                 cnt->dcs_when_free = cnt->dcs_when_active;
    7151                 :          0 :                 cnt_type = pool->is_aged ? MLX5_COUNTER_TYPE_AGE :
    7152                 :            :                                            MLX5_COUNTER_TYPE_ORIGIN;
    7153                 :          0 :                 rte_spinlock_lock(&priv->sh->sws_cmng.csl[cnt_type]);
    7154                 :          0 :                 TAILQ_INSERT_TAIL(&priv->sh->sws_cmng.counters[cnt_type],
    7155                 :            :                                   cnt, next);
    7156                 :          0 :                 rte_spinlock_unlock(&priv->sh->sws_cmng.csl[cnt_type]);
    7157                 :            :         }
    7158                 :            : }
    7159                 :            : 
    7160                 :            : /**
    7161                 :            :  * Resize a meter id container.
    7162                 :            :  *
    7163                 :            :  * @param[in] dev
    7164                 :            :  *   Pointer to the Ethernet device structure.
    7165                 :            :  *
    7166                 :            :  * @return
    7167                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
    7168                 :            :  */
    7169                 :            : static int
    7170                 :          0 : flow_dv_mtr_container_resize(struct rte_eth_dev *dev)
    7171                 :            : {
    7172                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7173                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7174                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7175                 :          0 :         void *old_pools = pools_mng->pools;
    7176                 :          0 :         uint32_t resize = pools_mng->n + MLX5_MTRS_CONTAINER_RESIZE;
    7177                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_mtr_pool *) * resize;
    7178                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
    7179                 :            : 
    7180         [ #  # ]:          0 :         if (!pools) {
    7181                 :          0 :                 rte_errno = ENOMEM;
    7182                 :          0 :                 return -ENOMEM;
    7183                 :            :         }
    7184         [ #  # ]:          0 :         if (!pools_mng->n)
    7185         [ #  # ]:          0 :                 if (mlx5_aso_queue_init(priv->sh, ASO_OPC_MOD_POLICER, 1)) {
    7186                 :          0 :                         mlx5_free(pools);
    7187                 :          0 :                         return -ENOMEM;
    7188                 :            :                 }
    7189         [ #  # ]:          0 :         if (old_pools)
    7190                 :          0 :                 memcpy(pools, old_pools, pools_mng->n *
    7191                 :            :                                        sizeof(struct mlx5_aso_mtr_pool *));
    7192                 :          0 :         pools_mng->n = resize;
    7193                 :          0 :         pools_mng->pools = pools;
    7194         [ #  # ]:          0 :         if (old_pools)
    7195                 :          0 :                 mlx5_free(old_pools);
    7196                 :            :         return 0;
    7197                 :            : }
    7198                 :            : 
    7199                 :            : /**
    7200                 :            :  * Prepare a new meter and/or a new meter pool.
    7201                 :            :  *
    7202                 :            :  * @param[in] dev
    7203                 :            :  *   Pointer to the Ethernet device structure.
    7204                 :            :  * @param[out] mtr_free
    7205                 :            :  *   Where to put the pointer of a new meter.g.
    7206                 :            :  *
    7207                 :            :  * @return
    7208                 :            :  *   The meter pool pointer and @mtr_free is set on success,
    7209                 :            :  *   NULL otherwise and rte_errno is set.
    7210                 :            :  */
    7211                 :            : static struct mlx5_aso_mtr_pool *
    7212                 :          0 : flow_dv_mtr_pool_create(struct rte_eth_dev *dev, struct mlx5_aso_mtr **mtr_free)
    7213                 :            : {
    7214                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7215                 :          0 :         struct mlx5_aso_mtr_pools_mng *pools_mng = &priv->sh->mtrmng->pools_mng;
    7216                 :            :         struct mlx5_aso_mtr_pool *pool = NULL;
    7217                 :            :         struct mlx5_devx_obj *dcs = NULL;
    7218                 :            :         uint32_t i;
    7219                 :            :         uint32_t log_obj_size;
    7220                 :            : 
    7221                 :            :         log_obj_size = rte_log2_u32(MLX5_ASO_MTRS_PER_POOL >> 1);
    7222                 :          0 :         dcs = mlx5_devx_cmd_create_flow_meter_aso_obj(priv->sh->cdev->ctx,
    7223                 :          0 :                                                       priv->sh->cdev->pdn,
    7224                 :            :                                                       log_obj_size);
    7225         [ #  # ]:          0 :         if (!dcs) {
    7226                 :          0 :                 rte_errno = ENODATA;
    7227                 :          0 :                 return NULL;
    7228                 :            :         }
    7229                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY);
    7230         [ #  # ]:          0 :         if (!pool) {
    7231                 :          0 :                 rte_errno = ENOMEM;
    7232                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
    7233                 :          0 :                 return NULL;
    7234                 :            :         }
    7235                 :          0 :         pool->devx_obj = dcs;
    7236                 :          0 :         rte_rwlock_write_lock(&pools_mng->resize_mtrwl);
    7237                 :          0 :         pool->index = pools_mng->n_valid;
    7238   [ #  #  #  # ]:          0 :         if (pool->index == pools_mng->n && flow_dv_mtr_container_resize(dev)) {
    7239                 :          0 :                 mlx5_free(pool);
    7240                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
    7241                 :            :                 rte_rwlock_write_unlock(&pools_mng->resize_mtrwl);
    7242                 :          0 :                 return NULL;
    7243                 :            :         }
    7244                 :          0 :         pools_mng->pools[pool->index] = pool;
    7245                 :          0 :         pools_mng->n_valid++;
    7246                 :            :         rte_rwlock_write_unlock(&pools_mng->resize_mtrwl);
    7247         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_MTRS_PER_POOL; ++i) {
    7248                 :          0 :                 pool->mtrs[i].offset = i;
    7249         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&pools_mng->meters, &pool->mtrs[i], next);
    7250                 :            :         }
    7251                 :          0 :         pool->mtrs[0].offset = 0;
    7252                 :          0 :         *mtr_free = &pool->mtrs[0];
    7253                 :          0 :         return pool;
    7254                 :            : }
    7255                 :            : 
    7256                 :            : /**
    7257                 :            :  * Release a flow meter into pool.
    7258                 :            :  *
    7259                 :            :  * @param[in] dev
    7260                 :            :  *   Pointer to the Ethernet device structure.
    7261                 :            :  * @param[in] mtr_idx
    7262                 :            :  *   Index to aso flow meter.
    7263                 :            :  */
    7264                 :            : static void
    7265                 :          0 : flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)
    7266                 :            : {
    7267                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7268                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7269                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7270                 :          0 :         struct mlx5_aso_mtr *aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
    7271                 :            : 
    7272                 :            :         MLX5_ASSERT(aso_mtr);
    7273                 :          0 :         rte_spinlock_lock(&pools_mng->mtrsl);
    7274         [ #  # ]:          0 :         memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
    7275                 :          0 :         aso_mtr->state = ASO_METER_FREE;
    7276         [ #  # ]:          0 :         LIST_INSERT_HEAD(&pools_mng->meters, aso_mtr, next);
    7277                 :            :         rte_spinlock_unlock(&pools_mng->mtrsl);
    7278                 :          0 : }
    7279                 :            : 
    7280                 :            : /**
    7281                 :            :  * Allocate a aso flow meter.
    7282                 :            :  *
    7283                 :            :  * @param[in] dev
    7284                 :            :  *   Pointer to the Ethernet device structure.
    7285                 :            :  *
    7286                 :            :  * @return
    7287                 :            :  *   Index to aso flow meter on success, 0 otherwise and rte_errno is set.
    7288                 :            :  */
    7289                 :            : static uint32_t
    7290                 :          0 : flow_dv_mtr_alloc(struct rte_eth_dev *dev)
    7291                 :            : {
    7292                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7293                 :          0 :         struct mlx5_aso_mtr *mtr_free = NULL;
    7294                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7295                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7296                 :            :         struct mlx5_aso_mtr_pool *pool;
    7297                 :            :         uint32_t mtr_idx = 0;
    7298                 :            : 
    7299         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
    7300                 :          0 :                 rte_errno = ENOTSUP;
    7301                 :          0 :                 return 0;
    7302                 :            :         }
    7303                 :            :         /* Allocate the flow meter memory. */
    7304                 :            :         /* Get free meters from management. */
    7305                 :          0 :         rte_spinlock_lock(&pools_mng->mtrsl);
    7306                 :          0 :         mtr_free = LIST_FIRST(&pools_mng->meters);
    7307         [ #  # ]:          0 :         if (mtr_free)
    7308         [ #  # ]:          0 :                 LIST_REMOVE(mtr_free, next);
    7309   [ #  #  #  # ]:          0 :         if (!mtr_free && !flow_dv_mtr_pool_create(dev, &mtr_free)) {
    7310                 :            :                 rte_spinlock_unlock(&pools_mng->mtrsl);
    7311                 :          0 :                 return 0;
    7312                 :            :         }
    7313                 :          0 :         mtr_free->state = ASO_METER_WAIT;
    7314                 :            :         rte_spinlock_unlock(&pools_mng->mtrsl);
    7315                 :          0 :         pool = container_of(mtr_free,
    7316                 :            :                         struct mlx5_aso_mtr_pool,
    7317                 :            :                         mtrs[mtr_free->offset]);
    7318                 :          0 :         mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);
    7319         [ #  # ]:          0 :         if (!mtr_free->fm.meter_action_g) {
    7320                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
    7321                 :            :                 struct rte_flow_error error;
    7322                 :            :                 uint8_t reg_id;
    7323                 :            : 
    7324                 :          0 :                 reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &error);
    7325                 :          0 :                 mtr_free->fm.meter_action_g =
    7326                 :          0 :                         mlx5_glue->dv_create_flow_action_aso
    7327                 :          0 :                                                 (priv->sh->rx_domain,
    7328                 :          0 :                                                  pool->devx_obj->obj,
    7329                 :            :                                                  mtr_free->offset,
    7330                 :            :                                                  (1 << MLX5_FLOW_COLOR_GREEN),
    7331                 :          0 :                                                  reg_id - REG_C_0);
    7332                 :            : #endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
    7333         [ #  # ]:          0 :                 if (!mtr_free->fm.meter_action_g) {
    7334                 :          0 :                         flow_dv_aso_mtr_release_to_pool(dev, mtr_idx);
    7335                 :          0 :                         return 0;
    7336                 :            :                 }
    7337                 :            :         }
    7338                 :            :         return mtr_idx;
    7339                 :            : }
    7340                 :            : 
    7341                 :            : /**
    7342                 :            :  * Verify the @p attributes will be correctly understood by the NIC and store
    7343                 :            :  * them in the @p flow if everything is correct.
    7344                 :            :  *
    7345                 :            :  * @param[in] dev
    7346                 :            :  *   Pointer to dev struct.
    7347                 :            :  * @param[in] attributes
    7348                 :            :  *   Pointer to flow attributes
    7349                 :            :  * @param[in] external
    7350                 :            :  *   This flow rule is created by request external to PMD.
    7351                 :            :  * @param[out] error
    7352                 :            :  *   Pointer to error structure.
    7353                 :            :  *
    7354                 :            :  * @return
    7355                 :            :  *   - 0 on success and non root table.
    7356                 :            :  *   - 1 on success and root table.
    7357                 :            :  *   - a negative errno value otherwise and rte_errno is set.
    7358                 :            :  */
    7359                 :            : static int
    7360                 :          0 : flow_dv_validate_attributes(struct rte_eth_dev *dev,
    7361                 :            :                             const struct mlx5_flow_tunnel *tunnel,
    7362                 :            :                             const struct rte_flow_attr *attributes,
    7363                 :            :                             const struct flow_grp_info *grp_info,
    7364                 :            :                             struct rte_flow_error *error)
    7365                 :            : {
    7366                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7367                 :          0 :         uint32_t lowest_priority = mlx5_get_lowest_priority(dev, attributes);
    7368                 :            :         int ret = 0;
    7369                 :            : 
    7370                 :            : #ifndef HAVE_MLX5DV_DR
    7371                 :            :         RTE_SET_USED(tunnel);
    7372                 :            :         RTE_SET_USED(grp_info);
    7373                 :            :         if (attributes->group)
    7374                 :            :                 return rte_flow_error_set(error, ENOTSUP,
    7375                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
    7376                 :            :                                           NULL,
    7377                 :            :                                           "groups are not supported");
    7378                 :            : #else
    7379                 :          0 :         uint32_t table = 0;
    7380                 :            : 
    7381                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, attributes->group, &table,
    7382                 :            :                                        grp_info, error);
    7383         [ #  # ]:          0 :         if (ret)
    7384                 :            :                 return ret;
    7385         [ #  # ]:          0 :         if (!table)
    7386                 :            :                 ret = MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL;
    7387                 :            : #endif
    7388   [ #  #  #  # ]:          0 :         if (attributes->priority != MLX5_FLOW_LOWEST_PRIO_INDICATOR &&
    7389                 :            :             attributes->priority > lowest_priority)
    7390                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7391                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
    7392                 :            :                                           NULL,
    7393                 :            :                                           "priority out of range");
    7394   [ #  #  #  # ]:          0 :         if (attributes->transfer && !priv->sh->config.dv_esw_en)
    7395                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7396                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    7397                 :            :                                           "E-Switch dr is not supported");
    7398         [ #  # ]:          0 :         if (attributes->ingress + attributes->egress + attributes->transfer != 1) {
    7399                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7400                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    7401                 :            :                                           "must specify exactly one of "
    7402                 :            :                                           "ingress, egress or transfer");
    7403                 :            :         }
    7404                 :            :         return ret;
    7405                 :            : }
    7406                 :            : 
    7407                 :            : static int
    7408                 :          0 : validate_integrity_bits(const void *arg,
    7409                 :            :                         int64_t pattern_flags, uint64_t l3_flags,
    7410                 :            :                         uint64_t l4_flags, uint64_t ip4_flag,
    7411                 :            :                         struct rte_flow_error *error)
    7412                 :            : {
    7413                 :            :         const struct rte_flow_item_integrity *mask = arg;
    7414                 :            : 
    7415   [ #  #  #  # ]:          0 :         if (mask->l3_ok && !(pattern_flags & l3_flags))
    7416                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7417                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7418                 :            :                                           NULL, "missing L3 protocol");
    7419                 :            : 
    7420   [ #  #  #  # ]:          0 :         if (mask->ipv4_csum_ok && !(pattern_flags & ip4_flag))
    7421                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7422                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7423                 :            :                                           NULL, "missing IPv4 protocol");
    7424                 :            : 
    7425   [ #  #  #  # ]:          0 :         if ((mask->l4_ok || mask->l4_csum_ok) && !(pattern_flags & l4_flags))
    7426                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7427                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7428                 :            :                                           NULL, "missing L4 protocol");
    7429                 :            : 
    7430                 :            :         return 0;
    7431                 :            : }
    7432                 :            : 
    7433                 :            : static int
    7434                 :          0 : flow_dv_validate_item_integrity_post(const struct
    7435                 :            :                                      rte_flow_item *integrity_items[2],
    7436                 :            :                                      int64_t pattern_flags,
    7437                 :            :                                      struct rte_flow_error *error)
    7438                 :            : {
    7439                 :            :         const struct rte_flow_item_integrity *mask;
    7440                 :            :         int ret;
    7441                 :            : 
    7442         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY) {
    7443                 :          0 :                 mask = (typeof(mask))integrity_items[0]->mask;
    7444                 :          0 :                 ret = validate_integrity_bits(mask, pattern_flags,
    7445                 :            :                                               MLX5_FLOW_LAYER_OUTER_L3,
    7446                 :            :                                               MLX5_FLOW_LAYER_OUTER_L4,
    7447                 :            :                                               MLX5_FLOW_LAYER_OUTER_L3_IPV4,
    7448                 :            :                                               error);
    7449         [ #  # ]:          0 :                 if (ret)
    7450                 :            :                         return ret;
    7451                 :            :         }
    7452         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY) {
    7453                 :          0 :                 mask = (typeof(mask))integrity_items[1]->mask;
    7454                 :          0 :                 ret = validate_integrity_bits(mask, pattern_flags,
    7455                 :            :                                               MLX5_FLOW_LAYER_INNER_L3,
    7456                 :            :                                               MLX5_FLOW_LAYER_INNER_L4,
    7457                 :            :                                               MLX5_FLOW_LAYER_INNER_L3_IPV4,
    7458                 :            :                                               error);
    7459         [ #  # ]:          0 :                 if (ret)
    7460                 :          0 :                         return ret;
    7461                 :            :         }
    7462                 :            :         return 0;
    7463                 :            : }
    7464                 :            : 
    7465                 :            : static int
    7466                 :          0 : flow_dv_validate_item_integrity(struct rte_eth_dev *dev,
    7467                 :            :                                 const struct rte_flow_item *integrity_item,
    7468                 :            :                                 uint64_t pattern_flags, uint64_t *last_item,
    7469                 :            :                                 const struct rte_flow_item *integrity_items[2],
    7470                 :            :                                 struct rte_flow_error *error)
    7471                 :            : {
    7472                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7473                 :          0 :         const struct rte_flow_item_integrity *mask = (typeof(mask))
    7474                 :            :                                                      integrity_item->mask;
    7475                 :          0 :         const struct rte_flow_item_integrity *spec = (typeof(spec))
    7476                 :            :                                                      integrity_item->spec;
    7477                 :            : 
    7478         [ #  # ]:          0 :         if (!priv->sh->cdev->config.hca_attr.pkt_integrity_match)
    7479                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7480                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7481                 :            :                                           integrity_item,
    7482                 :            :                                           "packet integrity integrity_item not supported");
    7483         [ #  # ]:          0 :         if (!spec)
    7484                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7485                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7486                 :            :                                           integrity_item,
    7487                 :            :                                           "no spec for integrity item");
    7488         [ #  # ]:          0 :         if (!mask)
    7489                 :            :                 mask = &rte_flow_item_integrity_mask;
    7490         [ #  # ]:          0 :         if (!mlx5_validate_integrity_item(mask))
    7491                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7492                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7493                 :            :                                           integrity_item,
    7494                 :            :                                           "unsupported integrity filter");
    7495   [ #  #  #  # ]:          0 :         if ((mask->l3_ok & !spec->l3_ok) || (mask->l4_ok & !spec->l4_ok) ||
    7496         [ #  # ]:          0 :                 (mask->ipv4_csum_ok & !spec->ipv4_csum_ok) ||
    7497         [ #  # ]:          0 :                 (mask->l4_csum_ok & !spec->l4_csum_ok))
    7498                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7499                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7500                 :            :                                           NULL, "negative integrity flow is not supported");
    7501         [ #  # ]:          0 :         if (spec->level > 1) {
    7502         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY)
    7503                 :          0 :                         return rte_flow_error_set
    7504                 :            :                                 (error, ENOTSUP,
    7505                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM,
    7506                 :            :                                  NULL, "multiple inner integrity items not supported");
    7507                 :          0 :                 integrity_items[1] = integrity_item;
    7508                 :          0 :                 *last_item |= MLX5_FLOW_ITEM_INNER_INTEGRITY;
    7509                 :            :         } else {
    7510         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY)
    7511                 :          0 :                         return rte_flow_error_set
    7512                 :            :                                 (error, ENOTSUP,
    7513                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM,
    7514                 :            :                                  NULL, "multiple outer integrity items not supported");
    7515                 :          0 :                 integrity_items[0] = integrity_item;
    7516                 :          0 :                 *last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
    7517                 :            :         }
    7518                 :            :         return 0;
    7519                 :            : }
    7520                 :            : 
    7521                 :            : static int
    7522                 :          0 : flow_dv_validate_item_flex(struct rte_eth_dev *dev,
    7523                 :            :                            const struct rte_flow_item *item,
    7524                 :            :                            uint64_t item_flags,
    7525                 :            :                            uint64_t *last_item,
    7526                 :            :                            bool is_inner,
    7527                 :            :                            struct rte_flow_error *error)
    7528                 :            : {
    7529                 :          0 :         const struct rte_flow_item_flex *flow_spec = item->spec;
    7530                 :          0 :         const struct rte_flow_item_flex *flow_mask = item->mask;
    7531                 :            :         struct mlx5_flex_item *flex;
    7532                 :            : 
    7533         [ #  # ]:          0 :         if (!flow_spec)
    7534                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7535                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7536                 :            :                                           "flex flow item spec cannot be NULL");
    7537         [ #  # ]:          0 :         if (!flow_mask)
    7538                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7539                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7540                 :            :                                           "flex flow item mask cannot be NULL");
    7541         [ #  # ]:          0 :         if (item->last)
    7542                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7543                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7544                 :            :                                           "flex flow item last not supported");
    7545         [ #  # ]:          0 :         if (mlx5_flex_acquire_index(dev, flow_spec->handle, false) < 0)
    7546                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7547                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7548                 :            :                                           "invalid flex flow item handle");
    7549                 :          0 :         flex = (struct mlx5_flex_item *)flow_spec->handle;
    7550   [ #  #  #  #  :          0 :         switch (flex->tunnel_mode) {
                   #  # ]
    7551                 :          0 :         case FLEX_TUNNEL_MODE_SINGLE:
    7552         [ #  # ]:          0 :                 if (item_flags &
    7553                 :            :                     (MLX5_FLOW_ITEM_OUTER_FLEX | MLX5_FLOW_ITEM_INNER_FLEX))
    7554                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7555                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7556                 :            :                                            NULL, "multiple flex items not supported");
    7557                 :            :                 break;
    7558                 :          0 :         case FLEX_TUNNEL_MODE_OUTER:
    7559         [ #  # ]:          0 :                 if (is_inner)
    7560                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7561                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7562                 :            :                                            NULL, "inner flex item was not configured");
    7563         [ #  # ]:          0 :                 if (item_flags & MLX5_FLOW_ITEM_OUTER_FLEX)
    7564                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    7565                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7566                 :            :                                            NULL, "multiple flex items not supported");
    7567                 :            :                 break;
    7568                 :          0 :         case FLEX_TUNNEL_MODE_INNER:
    7569         [ #  # ]:          0 :                 if (!is_inner)
    7570                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7571                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7572                 :            :                                            NULL, "outer flex item was not configured");
    7573         [ #  # ]:          0 :                 if (item_flags & MLX5_FLOW_ITEM_INNER_FLEX)
    7574                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7575                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7576                 :            :                                            NULL, "multiple flex items not supported");
    7577                 :            :                 break;
    7578                 :          0 :         case FLEX_TUNNEL_MODE_MULTI:
    7579   [ #  #  #  #  :          0 :                 if ((is_inner && (item_flags & MLX5_FLOW_ITEM_INNER_FLEX)) ||
                   #  # ]
    7580         [ #  # ]:          0 :                     (!is_inner && (item_flags & MLX5_FLOW_ITEM_OUTER_FLEX))) {
    7581                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7582                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7583                 :            :                                            NULL, "multiple flex items not supported");
    7584                 :            :                 }
    7585                 :            :                 break;
    7586                 :          0 :         case FLEX_TUNNEL_MODE_TUNNEL:
    7587   [ #  #  #  # ]:          0 :                 if (is_inner || (item_flags & MLX5_FLOW_ITEM_FLEX_TUNNEL))
    7588                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7589                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7590                 :            :                                            NULL, "multiple flex tunnel items not supported");
    7591                 :            :                 break;
    7592                 :          0 :         default:
    7593                 :          0 :                 rte_flow_error_set(error, EINVAL,
    7594                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM,
    7595                 :            :                                    NULL, "invalid flex item configuration");
    7596                 :            :         }
    7597                 :          0 :         *last_item = flex->tunnel_mode == FLEX_TUNNEL_MODE_TUNNEL ?
    7598         [ #  # ]:          0 :                      MLX5_FLOW_ITEM_FLEX_TUNNEL : is_inner ?
    7599         [ #  # ]:          0 :                      MLX5_FLOW_ITEM_INNER_FLEX : MLX5_FLOW_ITEM_OUTER_FLEX;
    7600                 :          0 :         return 0;
    7601                 :            : }
    7602                 :            : 
    7603                 :            : static __rte_always_inline uint8_t
    7604                 :            : mlx5_flow_l3_next_protocol(const struct rte_flow_item *l3_item,
    7605                 :            :                            enum MLX5_SET_MATCHER key_type)
    7606                 :            : {
    7607                 :            : #define MLX5_L3_NEXT_PROTOCOL(i, ms)                                            \
    7608                 :            :         ((i)->type == RTE_FLOW_ITEM_TYPE_IPV4 ?                                  \
    7609                 :            :         ((const struct rte_flow_item_ipv4 *)(i)->ms)->hdr.next_proto_id :       \
    7610                 :            :         (i)->type == RTE_FLOW_ITEM_TYPE_IPV6 ?                                  \
    7611                 :            :         ((const struct rte_flow_item_ipv6 *)(i)->ms)->hdr.proto :               \
    7612                 :            :         (i)->type == RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT ?                         \
    7613                 :            :         ((const struct rte_flow_item_ipv6_frag_ext *)(i)->ms)->hdr.next_header :\
    7614                 :            :         0xff)
    7615                 :            : 
    7616                 :            :         uint8_t next_protocol;
    7617                 :            : 
    7618   [ #  #  #  #  :          0 :         if (l3_item->mask != NULL && l3_item->spec != NULL) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    7619   [ #  #  #  #  :          0 :                 next_protocol = MLX5_L3_NEXT_PROTOCOL(l3_item, mask);
          #  #  #  #  #  
                #  #  # ]
    7620   [ #  #  #  #  :          0 :                 if (next_protocol)
          #  #  #  #  #  
                #  #  # ]
    7621   [ #  #  #  #  :          0 :                         next_protocol &= MLX5_L3_NEXT_PROTOCOL(l3_item, spec);
          #  #  #  #  #  
                #  #  # ]
    7622                 :            :                 else
    7623                 :            :                         next_protocol = 0xff;
    7624   [ #  #  #  #  :          0 :         } else if (key_type == MLX5_SET_MATCHER_HS_M && l3_item->mask != NULL) {
          #  #  #  #  #  
                #  #  # ]
    7625   [ #  #  #  #  :          0 :                 next_protocol =  MLX5_L3_NEXT_PROTOCOL(l3_item, mask);
                   #  # ]
    7626   [ #  #  #  #  :          0 :         } else if (key_type == MLX5_SET_MATCHER_HS_V && l3_item->spec != NULL) {
          #  #  #  #  #  
                #  #  # ]
    7627   [ #  #  #  #  :          0 :                 next_protocol =  MLX5_L3_NEXT_PROTOCOL(l3_item, spec);
                   #  # ]
    7628                 :            :         } else {
    7629                 :            :                 /* Reset for inner layer. */
    7630                 :            :                 next_protocol = 0xff;
    7631                 :            :         }
    7632                 :            :         return next_protocol;
    7633                 :            : 
    7634                 :            : #undef MLX5_L3_NEXT_PROTOCOL
    7635                 :            : }
    7636                 :            : 
    7637                 :            : /**
    7638                 :            :  * Validate IB BTH item.
    7639                 :            :  *
    7640                 :            :  * @param[in] dev
    7641                 :            :  *   Pointer to the rte_eth_dev structure.
    7642                 :            :  * @param[in] udp_dport
    7643                 :            :  *   UDP destination port
    7644                 :            :  * @param[in] item
    7645                 :            :  *   Item specification.
    7646                 :            :  * @param root
    7647                 :            :  *   Whether action is on root table.
    7648                 :            :  * @param[out] error
    7649                 :            :  *   Pointer to the error structure.
    7650                 :            :  *
    7651                 :            :  * @return
    7652                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    7653                 :            :  */
    7654                 :            : static int
    7655                 :          0 : mlx5_flow_validate_item_ib_bth(struct rte_eth_dev *dev,
    7656                 :            :                                uint16_t udp_dport,
    7657                 :            :                                const struct rte_flow_item *item,
    7658                 :            :                                bool root,
    7659                 :            :                                struct rte_flow_error *error)
    7660                 :            : {
    7661                 :          0 :         const struct rte_flow_item_ib_bth *mask = item->mask;
    7662                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7663                 :            :         const struct rte_flow_item_ib_bth *valid_mask;
    7664                 :            :         int ret;
    7665                 :            : 
    7666                 :            :         valid_mask = &rte_flow_item_ib_bth_mask;
    7667         [ #  # ]:          0 :         if (udp_dport && udp_dport != MLX5_UDP_PORT_ROCEv2)
    7668                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7669                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    7670                 :            :                                           "protocol filtering not compatible"
    7671                 :            :                                           " with UDP layer");
    7672   [ #  #  #  # ]:          0 :         if (mask && (mask->hdr.se || mask->hdr.m || mask->hdr.padcnt ||
    7673   [ #  #  #  # ]:          0 :                 mask->hdr.tver || mask->hdr.pkey || mask->hdr.f || mask->hdr.b ||
    7674         [ #  # ]:          0 :                 mask->hdr.rsvd0 || mask->hdr.a || mask->hdr.rsvd1 ||
    7675   [ #  #  #  #  :          0 :                 mask->hdr.psn[0] || mask->hdr.psn[1] || mask->hdr.psn[2]))
                   #  # ]
    7676                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7677                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    7678                 :            :                                           "only opcode and dst_qp are supported");
    7679   [ #  #  #  # ]:          0 :         if (root || priv->sh->steering_format_version ==
    7680                 :            :                 MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5)
    7681                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7682                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7683                 :            :                                           item,
    7684                 :            :                                           "IB BTH item is not supported");
    7685         [ #  # ]:          0 :         if (!mask)
    7686                 :            :                 mask = &rte_flow_item_ib_bth_mask;
    7687                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    7688                 :            :                                         (const uint8_t *)valid_mask,
    7689                 :            :                                         sizeof(struct rte_flow_item_ib_bth),
    7690                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    7691                 :            :         if (ret < 0)
    7692                 :            :                 return ret;
    7693                 :            :         return 0;
    7694                 :            : }
    7695                 :            : 
    7696                 :            : const struct rte_flow_item_ipv4 nic_ipv4_mask = {
    7697                 :            :         .hdr = {
    7698                 :            :                 .src_addr = RTE_BE32(0xffffffff),
    7699                 :            :                 .dst_addr = RTE_BE32(0xffffffff),
    7700                 :            :                 .type_of_service = 0xff,
    7701                 :            :                 .fragment_offset = RTE_BE16(0xffff),
    7702                 :            :                 .next_proto_id = 0xff,
    7703                 :            :                 .time_to_live = 0xff,
    7704                 :            :         },
    7705                 :            : };
    7706                 :            : 
    7707                 :            : const struct rte_flow_item_ipv6 nic_ipv6_mask = {
    7708                 :            :         .hdr = {
    7709                 :            :                 .src_addr = RTE_IPV6_MASK_FULL,
    7710                 :            :                 .dst_addr = RTE_IPV6_MASK_FULL,
    7711                 :            :                 .vtc_flow = RTE_BE32(0xffffffff),
    7712                 :            :                 .proto = 0xff,
    7713                 :            :                 .hop_limits = 0xff,
    7714                 :            :         },
    7715                 :            :         .has_frag_ext = 1,
    7716                 :            : };
    7717                 :            : 
    7718                 :            : const struct rte_flow_item_tcp nic_tcp_mask = {
    7719                 :            :         .hdr = {
    7720                 :            :                 .tcp_flags = 0xFF,
    7721                 :            :                 .src_port = RTE_BE16(UINT16_MAX),
    7722                 :            :                 .dst_port = RTE_BE16(UINT16_MAX),
    7723                 :            :         }
    7724                 :            : };
    7725                 :            : 
    7726                 :            : /**
    7727                 :            :  * Internal validation function. For validating both actions and items.
    7728                 :            :  *
    7729                 :            :  * @param[in] dev
    7730                 :            :  *   Pointer to the rte_eth_dev structure.
    7731                 :            :  * @param[in] attr
    7732                 :            :  *   Pointer to the flow attributes.
    7733                 :            :  * @param[in] items
    7734                 :            :  *   Pointer to the list of items.
    7735                 :            :  * @param[in] actions
    7736                 :            :  *   Pointer to the list of actions.
    7737                 :            :  * @param[in] external
    7738                 :            :  *   This flow rule is created by request external to PMD.
    7739                 :            :  * @param[in] hairpin
    7740                 :            :  *   Number of hairpin TX actions, 0 means classic flow.
    7741                 :            :  * @param[out] error
    7742                 :            :  *   Pointer to the error structure.
    7743                 :            :  *
    7744                 :            :  * @return
    7745                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    7746                 :            :  */
    7747                 :            : int
    7748                 :          0 : flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
    7749                 :            :                  const struct rte_flow_item items[],
    7750                 :            :                  const struct rte_flow_action actions[],
    7751                 :            :                  bool external, int hairpin, struct rte_flow_error *error)
    7752                 :            : {
    7753                 :            :         int ret;
    7754                 :          0 :         uint64_t aso_mask, action_flags = 0;
    7755                 :          0 :         uint64_t item_flags = 0;
    7756                 :          0 :         uint64_t last_item = 0;
    7757                 :            :         uint8_t next_protocol = 0xff;
    7758                 :            :         uint16_t ether_type = 0;
    7759                 :          0 :         int actions_n = 0;
    7760                 :            :         uint8_t item_ipv6_proto = 0;
    7761                 :          0 :         int fdb_mirror = 0;
    7762                 :            :         int modify_after_mirror = 0;
    7763                 :            :         const struct rte_flow_item *geneve_item = NULL;
    7764                 :            :         const struct rte_flow_item *gre_item = NULL;
    7765                 :            :         const struct rte_flow_item *gtp_item = NULL;
    7766                 :            :         const struct rte_flow_action_raw_decap *decap;
    7767                 :            :         const struct rte_flow_action_raw_encap *encap;
    7768                 :            :         const struct rte_flow_action_rss *rss = NULL;
    7769                 :          0 :         const struct rte_flow_action_rss *sample_rss = NULL;
    7770                 :          0 :         const struct rte_flow_action_count *sample_count = NULL;
    7771                 :          0 :         const struct rte_flow_item_ecpri nic_ecpri_mask = {
    7772                 :            :                 .hdr = {
    7773                 :            :                         .common = {
    7774                 :            :                                 .u32 =
    7775                 :            :                                 RTE_BE32(((const struct rte_ecpri_common_hdr) {
    7776                 :            :                                         .type = 0xFF,
    7777                 :            :                                         }).u32),
    7778                 :            :                         },
    7779                 :            :                         .dummy[0] = 0xffffffff,
    7780                 :            :                 },
    7781                 :            :         };
    7782                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7783                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
    7784                 :            :         uint16_t queue_index = 0xFFFF;
    7785                 :            :         const struct rte_flow_item_vlan *vlan_m = NULL;
    7786                 :            :         uint32_t rw_act_num = 0;
    7787                 :            :         uint64_t is_root;
    7788                 :            :         const struct mlx5_flow_tunnel *tunnel;
    7789                 :            :         enum mlx5_tof_rule_type tof_rule_type;
    7790                 :          0 :         struct flow_grp_info grp_info = {
    7791                 :            :                 .external = !!external,
    7792                 :          0 :                 .transfer = !!attr->transfer,
    7793                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
    7794                 :            :                 .std_tbl_fix = true,
    7795                 :            :         };
    7796                 :            :         const struct rte_eth_hairpin_conf *conf;
    7797                 :          0 :         const struct rte_flow_item *integrity_items[2] = {NULL, NULL};
    7798                 :            :         const struct rte_flow_item *port_id_item = NULL;
    7799                 :          0 :         bool def_policy = false;
    7800                 :            :         bool shared_count = false;
    7801                 :            :         uint16_t udp_dport = 0;
    7802                 :          0 :         uint32_t tag_id = 0, tag_bitmap = 0;
    7803                 :            :         const struct rte_flow_action_age *non_shared_age = NULL;
    7804                 :            :         const struct rte_flow_action_count *count = NULL;
    7805                 :            :         const struct rte_flow_action_port_id *port = NULL;
    7806                 :            :         const struct mlx5_rte_flow_item_tag *mlx5_tag;
    7807                 :          0 :         struct mlx5_priv *act_priv = NULL;
    7808                 :            :         int aso_after_sample = 0;
    7809                 :            :         struct mlx5_priv *port_priv = NULL;
    7810                 :          0 :         uint64_t sub_action_flags = 0;
    7811                 :          0 :         uint16_t sample_port_id = 0;
    7812                 :            :         uint16_t port_id = 0;
    7813                 :            : 
    7814         [ #  # ]:          0 :         if (items == NULL)
    7815                 :            :                 return -1;
    7816                 :            :         tunnel = is_tunnel_offload_active(dev) ?
    7817         [ #  # ]:          0 :                  mlx5_get_tof(items, actions, &tof_rule_type) : NULL;
    7818         [ #  # ]:          0 :         if (tunnel) {
    7819         [ #  # ]:          0 :                 if (!dev_conf->dv_flow_en)
    7820                 :          0 :                         return rte_flow_error_set
    7821                 :            :                                 (error, ENOTSUP,
    7822                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    7823                 :            :                                  NULL, "tunnel offload requires DV flow interface");
    7824         [ #  # ]:          0 :                 if (priv->representor)
    7825                 :          0 :                         return rte_flow_error_set
    7826                 :            :                                 (error, ENOTSUP,
    7827                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    7828                 :            :                                  NULL, "decap not supported for VF representor");
    7829         [ #  # ]:          0 :                 if (tof_rule_type == MLX5_TUNNEL_OFFLOAD_SET_RULE)
    7830                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;
    7831         [ #  # ]:          0 :                 else if (tof_rule_type == MLX5_TUNNEL_OFFLOAD_MATCH_RULE)
    7832                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_MATCH |
    7833                 :            :                                         MLX5_FLOW_ACTION_DECAP;
    7834                 :          0 :                 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
    7835                 :            :                                         (dev, attr, tunnel, tof_rule_type);
    7836                 :            :         }
    7837                 :          0 :         ret = flow_dv_validate_attributes(dev, tunnel, attr, &grp_info, error);
    7838         [ #  # ]:          0 :         if (ret < 0)
    7839                 :            :                 return ret;
    7840                 :          0 :         is_root = (uint64_t)ret;
    7841         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    7842                 :            :                 enum mlx5_l3_tunnel_detection l3_tunnel_detection;
    7843                 :            :                 uint64_t l3_tunnel_flag;
    7844                 :          0 :                 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    7845                 :          0 :                 int type = items->type;
    7846                 :            : 
    7847                 :            :                 if (!mlx5_flow_os_item_supported(type))
    7848                 :            :                         return rte_flow_error_set(error, ENOTSUP,
    7849                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    7850                 :            :                                                   NULL, "item not supported");
    7851   [ #  #  #  #  :          0 :                 switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    7852                 :            :                 case RTE_FLOW_ITEM_TYPE_VOID:
    7853                 :            :                         break;
    7854                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ESP:
    7855                 :          0 :                         ret = mlx5_flow_os_validate_item_esp(dev, items,
    7856                 :            :                                                              item_flags,
    7857                 :            :                                                              next_protocol,
    7858                 :            :                                                              error);
    7859         [ #  # ]:          0 :                         if (ret < 0)
    7860                 :          0 :                                 return ret;
    7861                 :          0 :                         last_item = MLX5_FLOW_ITEM_ESP;
    7862                 :          0 :                         break;
    7863                 :          0 :                 case RTE_FLOW_ITEM_TYPE_PORT_ID:
    7864                 :          0 :                         ret = flow_dv_validate_item_port_id
    7865                 :            :                                         (dev, items, attr, item_flags, &act_priv, error);
    7866         [ #  # ]:          0 :                         if (ret < 0)
    7867                 :          0 :                                 return ret;
    7868                 :          0 :                         last_item = MLX5_FLOW_ITEM_PORT_ID;
    7869                 :            :                         port_id_item = items;
    7870                 :          0 :                         break;
    7871                 :          0 :                 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
    7872                 :            :                 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
    7873                 :          0 :                         ret = flow_dv_validate_item_represented_port
    7874                 :            :                                         (dev, items, attr, item_flags, &act_priv, error);
    7875         [ #  # ]:          0 :                         if (ret < 0)
    7876                 :          0 :                                 return ret;
    7877                 :          0 :                         last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
    7878                 :            :                         port_id_item = items;
    7879                 :          0 :                         break;
    7880                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    7881                 :          0 :                         ret = mlx5_flow_validate_item_eth(dev, items, item_flags,
    7882                 :            :                                                           true, error);
    7883         [ #  # ]:          0 :                         if (ret < 0)
    7884                 :          0 :                                 return ret;
    7885         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
    7886                 :            :                                              MLX5_FLOW_LAYER_OUTER_L2;
    7887   [ #  #  #  # ]:          0 :                         if (items->mask != NULL && items->spec != NULL) {
    7888                 :          0 :                                 ether_type =
    7889                 :            :                                         ((const struct rte_flow_item_eth *)
    7890                 :            :                                          items->spec)->hdr.ether_type;
    7891                 :          0 :                                 ether_type &=
    7892                 :            :                                         ((const struct rte_flow_item_eth *)
    7893                 :          0 :                                          items->mask)->hdr.ether_type;
    7894         [ #  # ]:          0 :                                 ether_type = rte_be_to_cpu_16(ether_type);
    7895                 :            :                         } else {
    7896                 :            :                                 ether_type = 0;
    7897                 :            :                         }
    7898                 :            :                         break;
    7899                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    7900                 :          0 :                         ret = mlx5_flow_dv_validate_item_vlan(items, item_flags,
    7901                 :            :                                                               dev, error);
    7902         [ #  # ]:          0 :                         if (ret < 0)
    7903                 :          0 :                                 return ret;
    7904         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
    7905                 :            :                                              MLX5_FLOW_LAYER_OUTER_VLAN;
    7906   [ #  #  #  # ]:          0 :                         if (items->mask != NULL && items->spec != NULL) {
    7907                 :          0 :                                 ether_type =
    7908                 :            :                                         ((const struct rte_flow_item_vlan *)
    7909                 :            :                                          items->spec)->hdr.eth_proto;
    7910                 :          0 :                                 ether_type &=
    7911                 :            :                                         ((const struct rte_flow_item_vlan *)
    7912                 :          0 :                                          items->mask)->hdr.eth_proto;
    7913         [ #  # ]:          0 :                                 ether_type = rte_be_to_cpu_16(ether_type);
    7914                 :            :                         } else {
    7915                 :            :                                 ether_type = 0;
    7916                 :            :                         }
    7917                 :            :                         /* Store outer VLAN mask for of_push_vlan action. */
    7918         [ #  # ]:          0 :                         if (!tunnel)
    7919                 :            :                                 vlan_m = items->mask;
    7920                 :            :                         break;
    7921                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    7922                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7923                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7924                 :            :                         l3_tunnel_detection =
    7925                 :            :                                 mlx5_flow_tunnel_ip_check(items, next_protocol,
    7926                 :            :                                                           item_flags,
    7927                 :            :                                                           &l3_tunnel_flag);
    7928                 :            :                         if (l3_tunnel_detection == l3_tunnel_inner) {
    7929                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7930                 :            :                                 tunnel = 1;
    7931                 :            :                         }
    7932                 :          0 :                         ret = mlx5_flow_dv_validate_item_ipv4(dev, items,
    7933                 :            :                                                               item_flags,
    7934                 :            :                                                               last_item,
    7935                 :            :                                                               ether_type,
    7936                 :            :                                                               &nic_ipv4_mask,
    7937                 :            :                                                               error);
    7938         [ #  # ]:          0 :                         if (ret < 0)
    7939                 :          0 :                                 return ret;
    7940         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    7941                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    7942         [ #  # ]:          0 :                         if (l3_tunnel_detection == l3_tunnel_outer)
    7943                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7944                 :            :                         break;
    7945                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    7946                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7947                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7948                 :            :                         l3_tunnel_detection =
    7949                 :            :                                 mlx5_flow_tunnel_ip_check(items, next_protocol,
    7950                 :            :                                                           item_flags,
    7951                 :            :                                                           &l3_tunnel_flag);
    7952                 :            :                         if (l3_tunnel_detection == l3_tunnel_inner) {
    7953                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7954                 :            :                                 tunnel = 1;
    7955                 :            :                         }
    7956                 :          0 :                         ret = mlx5_flow_validate_item_ipv6(dev, items,
    7957                 :            :                                                            item_flags,
    7958                 :            :                                                            last_item,
    7959                 :            :                                                            ether_type,
    7960                 :            :                                                            &nic_ipv6_mask,
    7961                 :            :                                                            error);
    7962         [ #  # ]:          0 :                         if (ret < 0)
    7963                 :          0 :                                 return ret;
    7964         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    7965                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    7966         [ #  # ]:          0 :                         if (l3_tunnel_detection == l3_tunnel_outer)
    7967                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7968                 :            :                         break;
    7969                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
    7970                 :          0 :                         ret = flow_dv_validate_item_ipv6_frag_ext(dev, items,
    7971                 :            :                                                                   item_flags,
    7972                 :            :                                                                   error);
    7973         [ #  # ]:          0 :                         if (ret < 0)
    7974                 :          0 :                                 return ret;
    7975         [ #  # ]:          0 :                         last_item = tunnel ?
    7976         [ #  # ]:          0 :                                         MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT :
    7977                 :            :                                         MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT;
    7978                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7979                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7980                 :            :                         break;
    7981                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
    7982                 :          0 :                         ret = mlx5_flow_validate_item_tcp
    7983                 :            :                                                 (dev, items, item_flags,
    7984                 :            :                                                  next_protocol,
    7985                 :            :                                                  &nic_tcp_mask,
    7986                 :            :                                                  error);
    7987         [ #  # ]:          0 :                         if (ret < 0)
    7988                 :          0 :                                 return ret;
    7989         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
    7990                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_TCP;
    7991                 :          0 :                         break;
    7992                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    7993                 :          0 :                         ret = mlx5_flow_validate_item_udp(dev, items, item_flags,
    7994                 :            :                                                           next_protocol,
    7995                 :            :                                                           error);
    7996                 :          0 :                         const struct rte_flow_item_udp *spec = items->spec;
    7997                 :          0 :                         const struct rte_flow_item_udp *mask = items->mask;
    7998         [ #  # ]:          0 :                         if (!mask)
    7999                 :            :                                 mask = &rte_flow_item_udp_mask;
    8000         [ #  # ]:          0 :                         if (spec != NULL)
    8001         [ #  # ]:          0 :                                 udp_dport = rte_be_to_cpu_16
    8002                 :            :                                                 (spec->hdr.dst_port &
    8003                 :            :                                                  mask->hdr.dst_port);
    8004         [ #  # ]:          0 :                         if (ret < 0)
    8005                 :          0 :                                 return ret;
    8006         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
    8007                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_UDP;
    8008                 :          0 :                         break;
    8009                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
    8010                 :          0 :                         ret = mlx5_flow_validate_item_gre(dev, items, item_flags,
    8011                 :            :                                                           next_protocol, error);
    8012         [ #  # ]:          0 :                         if (ret < 0)
    8013                 :          0 :                                 return ret;
    8014                 :            :                         gre_item = items;
    8015                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE;
    8016                 :          0 :                         break;
    8017                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
    8018                 :          0 :                         ret = mlx5_flow_validate_item_gre_option(dev, items, item_flags,
    8019                 :            :                                                           attr, gre_item, error);
    8020         [ #  # ]:          0 :                         if (ret < 0)
    8021                 :          0 :                                 return ret;
    8022                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE;
    8023                 :          0 :                         break;
    8024                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    8025                 :          0 :                         ret = mlx5_flow_validate_item_nvgre(dev, items,
    8026                 :            :                                                             item_flags,
    8027                 :            :                                                             next_protocol,
    8028                 :            :                                                             error);
    8029         [ #  # ]:          0 :                         if (ret < 0)
    8030                 :          0 :                                 return ret;
    8031                 :          0 :                         last_item = MLX5_FLOW_LAYER_NVGRE;
    8032                 :          0 :                         break;
    8033                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
    8034                 :          0 :                         ret = mlx5_flow_validate_item_gre_key
    8035                 :            :                                 (dev, items, item_flags, gre_item, error);
    8036         [ #  # ]:          0 :                         if (ret < 0)
    8037                 :          0 :                                 return ret;
    8038                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE_KEY;
    8039                 :          0 :                         break;
    8040                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    8041                 :          0 :                         ret = mlx5_flow_validate_item_vxlan(dev, udp_dport,
    8042                 :            :                                                             items, item_flags,
    8043                 :            :                                                             is_root, error);
    8044         [ #  # ]:          0 :                         if (ret < 0)
    8045                 :          0 :                                 return ret;
    8046                 :          0 :                         last_item = MLX5_FLOW_LAYER_VXLAN;
    8047                 :          0 :                         break;
    8048                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    8049                 :          0 :                         ret = mlx5_flow_validate_item_vxlan_gpe(items,
    8050                 :            :                                                                 item_flags, dev,
    8051                 :            :                                                                 error);
    8052         [ #  # ]:          0 :                         if (ret < 0)
    8053                 :          0 :                                 return ret;
    8054                 :          0 :                         last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
    8055                 :          0 :                         break;
    8056                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
    8057                 :          0 :                         ret = mlx5_flow_validate_item_geneve(items,
    8058                 :            :                                                              item_flags, dev,
    8059                 :            :                                                              error);
    8060         [ #  # ]:          0 :                         if (ret < 0)
    8061                 :          0 :                                 return ret;
    8062                 :            :                         geneve_item = items;
    8063                 :          0 :                         last_item = MLX5_FLOW_LAYER_GENEVE;
    8064                 :          0 :                         break;
    8065                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
    8066                 :          0 :                         ret = mlx5_flow_validate_item_geneve_opt(items,
    8067                 :            :                                                                  last_item,
    8068                 :            :                                                                  geneve_item,
    8069                 :            :                                                                  dev,
    8070                 :            :                                                                  error);
    8071         [ #  # ]:          0 :                         if (ret < 0)
    8072                 :          0 :                                 return ret;
    8073                 :          0 :                         last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
    8074                 :          0 :                         break;
    8075                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MPLS:
    8076                 :          0 :                         ret = mlx5_flow_validate_item_mpls(dev, items,
    8077                 :            :                                                            item_flags,
    8078                 :            :                                                            last_item, error);
    8079         [ #  # ]:          0 :                         if (ret < 0)
    8080                 :          0 :                                 return ret;
    8081                 :          0 :                         last_item = MLX5_FLOW_LAYER_MPLS;
    8082                 :          0 :                         break;
    8083                 :            : 
    8084                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MARK:
    8085                 :          0 :                         ret = flow_dv_validate_item_mark(dev, items, attr,
    8086                 :            :                                                          error);
    8087         [ #  # ]:          0 :                         if (ret < 0)
    8088                 :          0 :                                 return ret;
    8089                 :          0 :                         last_item = MLX5_FLOW_ITEM_MARK;
    8090                 :          0 :                         break;
    8091                 :          0 :                 case RTE_FLOW_ITEM_TYPE_META:
    8092                 :          0 :                         ret = flow_dv_validate_item_meta(dev, items, attr,
    8093                 :            :                                                          error);
    8094         [ #  # ]:          0 :                         if (ret < 0)
    8095                 :          0 :                                 return ret;
    8096                 :          0 :                         last_item = MLX5_FLOW_ITEM_METADATA;
    8097                 :          0 :                         break;
    8098                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP:
    8099                 :          0 :                         ret = mlx5_flow_validate_item_icmp(dev, items, item_flags,
    8100                 :            :                                                            next_protocol,
    8101                 :            :                                                            error);
    8102         [ #  # ]:          0 :                         if (ret < 0)
    8103                 :          0 :                                 return ret;
    8104                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP;
    8105                 :          0 :                         break;
    8106                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6:
    8107                 :          0 :                         ret = mlx5_flow_validate_item_icmp6(dev, items, item_flags,
    8108                 :            :                                                             next_protocol,
    8109                 :            :                                                             error);
    8110         [ #  # ]:          0 :                         if (ret < 0)
    8111                 :          0 :                                 return ret;
    8112                 :            :                         item_ipv6_proto = IPPROTO_ICMPV6;
    8113                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8114                 :          0 :                         break;
    8115                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
    8116                 :            :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
    8117                 :          0 :                         ret = mlx5_flow_validate_item_icmp6_echo(dev, items,
    8118                 :            :                                                                  item_flags,
    8119                 :            :                                                                  next_protocol,
    8120                 :            :                                                                  error);
    8121         [ #  # ]:          0 :                         if (ret < 0)
    8122                 :          0 :                                 return ret;
    8123                 :            :                         item_ipv6_proto = IPPROTO_ICMPV6;
    8124                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8125                 :          0 :                         break;
    8126                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TAG:
    8127                 :          0 :                         ret = flow_dv_validate_item_tag(dev, items, &tag_bitmap,
    8128                 :            :                                                         attr, error);
    8129         [ #  # ]:          0 :                         if (ret < 0)
    8130                 :          0 :                                 return ret;
    8131                 :          0 :                         last_item = MLX5_FLOW_ITEM_TAG;
    8132                 :          0 :                         break;
    8133                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
    8134                 :            :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
    8135                 :          0 :                         last_item = MLX5_FLOW_ITEM_SQ;
    8136                 :          0 :                         break;
    8137                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
    8138                 :          0 :                         mlx5_tag = (const struct mlx5_rte_flow_item_tag *)items->spec;
    8139         [ #  # ]:          0 :                         if (tag_bitmap & (1 << mlx5_tag->id))
    8140                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8141                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    8142                 :            :                                                           items->spec,
    8143                 :            :                                                           "Duplicated tag index");
    8144                 :          0 :                         tag_bitmap |= 1 << mlx5_tag->id;
    8145                 :          0 :                         break;
    8146                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP:
    8147                 :          0 :                         ret = mlx5_flow_dv_validate_item_gtp(dev, items,
    8148                 :            :                                                              item_flags,
    8149                 :            :                                                              error);
    8150         [ #  # ]:          0 :                         if (ret < 0)
    8151                 :          0 :                                 return ret;
    8152                 :            :                         gtp_item = items;
    8153                 :          0 :                         last_item = MLX5_FLOW_LAYER_GTP;
    8154                 :          0 :                         break;
    8155                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
    8156                 :          0 :                         ret = mlx5_flow_dv_validate_item_gtp_psc(dev, items,
    8157                 :            :                                                                  last_item,
    8158                 :            :                                                                  gtp_item,
    8159                 :            :                                                                  is_root, error);
    8160         [ #  # ]:          0 :                         if (ret < 0)
    8161                 :          0 :                                 return ret;
    8162                 :          0 :                         last_item = MLX5_FLOW_LAYER_GTP_PSC;
    8163                 :          0 :                         break;
    8164                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ECPRI:
    8165                 :            :                         /* Capacity will be checked in the translate stage. */
    8166                 :          0 :                         ret = mlx5_flow_validate_item_ecpri(dev, items,
    8167                 :            :                                                             item_flags,
    8168                 :            :                                                             last_item,
    8169                 :            :                                                             ether_type,
    8170                 :            :                                                             &nic_ecpri_mask,
    8171                 :            :                                                             error);
    8172         [ #  # ]:          0 :                         if (ret < 0)
    8173                 :          0 :                                 return ret;
    8174                 :          0 :                         last_item = MLX5_FLOW_LAYER_ECPRI;
    8175                 :          0 :                         break;
    8176                 :          0 :                 case RTE_FLOW_ITEM_TYPE_INTEGRITY:
    8177                 :          0 :                         ret = flow_dv_validate_item_integrity(dev, items,
    8178                 :            :                                                               item_flags,
    8179                 :            :                                                               &last_item,
    8180                 :            :                                                               integrity_items,
    8181                 :            :                                                               error);
    8182         [ #  # ]:          0 :                         if (ret < 0)
    8183                 :          0 :                                 return ret;
    8184                 :            :                         break;
    8185                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
    8186                 :          0 :                         ret = mlx5_flow_dv_validate_item_aso_ct(dev, items,
    8187                 :            :                                                                 &item_flags,
    8188                 :            :                                                                 error);
    8189         [ #  # ]:          0 :                         if (ret < 0)
    8190                 :          0 :                                 return ret;
    8191                 :          0 :                         last_item = MLX5_FLOW_LAYER_ASO_CT;
    8192                 :          0 :                         break;
    8193                 :            :                 case MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL:
    8194                 :            :                         /* tunnel offload item was processed before
    8195                 :            :                          * list it here as a supported type
    8196                 :            :                          */
    8197                 :            :                         break;
    8198                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
    8199                 :          0 :                         ret = flow_dv_validate_item_flex(dev, items, item_flags,
    8200                 :            :                                                          &last_item,
    8201                 :            :                                                          tunnel != 0, error);
    8202         [ #  # ]:          0 :                         if (ret < 0)
    8203                 :          0 :                                 return ret;
    8204                 :            :                         /* Reset for next proto, it is unknown. */
    8205                 :            :                         next_protocol = 0xff;
    8206                 :            :                         break;
    8207                 :          0 :                 case RTE_FLOW_ITEM_TYPE_METER_COLOR:
    8208                 :          0 :                         ret = flow_dv_validate_item_meter_color(dev, items,
    8209                 :            :                                                                 attr, error);
    8210         [ #  # ]:          0 :                         if (ret < 0)
    8211                 :          0 :                                 return ret;
    8212                 :          0 :                         last_item = MLX5_FLOW_ITEM_METER_COLOR;
    8213                 :          0 :                         break;
    8214                 :          0 :                 case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
    8215                 :          0 :                         ret = flow_dv_validate_item_aggr_affinity(dev, items,
    8216                 :            :                                                                   attr, error);
    8217         [ #  # ]:          0 :                         if (ret < 0)
    8218                 :          0 :                                 return ret;
    8219                 :          0 :                         last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
    8220                 :          0 :                         break;
    8221                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IB_BTH:
    8222                 :          0 :                         ret = mlx5_flow_validate_item_ib_bth(dev, udp_dport,
    8223                 :            :                                                             items, is_root, error);
    8224         [ #  # ]:          0 :                         if (ret < 0)
    8225                 :          0 :                                 return ret;
    8226                 :            : 
    8227                 :          0 :                         last_item = MLX5_FLOW_ITEM_IB_BTH;
    8228                 :          0 :                         break;
    8229                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NSH:
    8230                 :          0 :                         ret = mlx5_flow_validate_item_nsh(dev, items, error);
    8231         [ #  # ]:          0 :                         if (ret < 0)
    8232                 :          0 :                                 return ret;
    8233                 :          0 :                         last_item = MLX5_FLOW_ITEM_NSH;
    8234                 :          0 :                         break;
    8235                 :          0 :                 default:
    8236                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8237                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    8238                 :            :                                                   NULL, "item not supported");
    8239                 :            :                 }
    8240                 :          0 :                 item_flags |= last_item;
    8241                 :            :         }
    8242         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
    8243                 :          0 :                 ret = flow_dv_validate_item_integrity_post(integrity_items,
    8244                 :            :                                                            item_flags, error);
    8245         [ #  # ]:          0 :                 if (ret)
    8246                 :            :                         return ret;
    8247                 :            :         }
    8248         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    8249                 :          0 :                 int type = actions->type;
    8250                 :            : 
    8251                 :            :                 if (!mlx5_flow_os_action_supported(type))
    8252                 :            :                         return rte_flow_error_set(error, ENOTSUP,
    8253                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8254                 :            :                                                   actions,
    8255                 :            :                                                   "action not supported");
    8256         [ #  # ]:          0 :                 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
    8257                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8258                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8259                 :            :                                                   actions, "too many actions");
    8260         [ #  # ]:          0 :                 if (action_flags &
    8261                 :            :                         MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
    8262                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8263                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8264                 :            :                                 NULL, "meter action with policy "
    8265                 :            :                                 "must be the last action");
    8266   [ #  #  #  #  :          0 :                 switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    8267                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    8268                 :            :                         break;
    8269                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
    8270                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    8271                 :          0 :                         ret = flow_dv_validate_action_port_id(dev,
    8272                 :            :                                                               action_flags,
    8273                 :            :                                                               actions,
    8274                 :            :                                                               attr,
    8275                 :            :                                                               error);
    8276         [ #  # ]:          0 :                         if (ret)
    8277                 :          0 :                                 return ret;
    8278         [ #  # ]:          0 :                         if (type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
    8279                 :          0 :                                 port = (const struct rte_flow_action_port_id *)
    8280                 :            :                                         actions->conf;
    8281         [ #  # ]:          0 :                                 port_id = port->original ? dev->data->port_id : port->id;
    8282                 :            :                         } else {
    8283                 :          0 :                                 port_id = ((const struct rte_flow_action_ethdev *)
    8284                 :          0 :                                         actions->conf)->port_id;
    8285                 :            :                         }
    8286                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
    8287                 :          0 :                         ++actions_n;
    8288                 :          0 :                         break;
    8289                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    8290                 :          0 :                         ret = flow_dv_validate_action_flag(dev, action_flags,
    8291                 :            :                                                            attr, error);
    8292         [ #  # ]:          0 :                         if (ret < 0)
    8293                 :          0 :                                 return ret;
    8294         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    8295                 :            :                                 /* Count all modify-header actions as one. */
    8296         [ #  # ]:          0 :                                 if (!(action_flags &
    8297                 :            :                                       MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8298                 :          0 :                                         ++actions_n;
    8299                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_FLAG |
    8300                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    8301         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8302                 :            :                                         modify_after_mirror = 1;
    8303                 :            : 
    8304                 :            :                         } else {
    8305                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_FLAG;
    8306                 :          0 :                                 ++actions_n;
    8307                 :            :                         }
    8308                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_MARK;
    8309                 :          0 :                         break;
    8310                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    8311                 :          0 :                         ret = flow_dv_validate_action_mark(dev, actions,
    8312                 :            :                                                            action_flags,
    8313                 :            :                                                            attr, error);
    8314         [ #  # ]:          0 :                         if (ret < 0)
    8315                 :          0 :                                 return ret;
    8316         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    8317                 :            :                                 /* Count all modify-header actions as one. */
    8318         [ #  # ]:          0 :                                 if (!(action_flags &
    8319                 :            :                                       MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8320                 :          0 :                                         ++actions_n;
    8321                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK |
    8322                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    8323         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8324                 :            :                                         modify_after_mirror = 1;
    8325                 :            :                         } else {
    8326                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK;
    8327                 :          0 :                                 ++actions_n;
    8328                 :            :                         }
    8329                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_MARK;
    8330                 :          0 :                         break;
    8331                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_META:
    8332         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    8333                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8334                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8335                 :            :                                                   actions,
    8336                 :            :                                                   "action not supported");
    8337                 :          0 :                         ret = flow_dv_validate_action_set_meta(dev, actions,
    8338                 :            :                                                                action_flags,
    8339                 :            :                                                                attr, error);
    8340         [ #  # ]:          0 :                         if (ret < 0)
    8341                 :          0 :                                 return ret;
    8342                 :            :                         /* Count all modify-header actions as one action. */
    8343         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8344                 :          0 :                                 ++actions_n;
    8345         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8346                 :            :                                 modify_after_mirror = 1;
    8347                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_META;
    8348                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_META;
    8349                 :          0 :                         break;
    8350                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
    8351                 :          0 :                         ret = flow_dv_validate_action_set_tag(dev, actions,
    8352                 :            :                                                               action_flags,
    8353                 :            :                                                               attr, error);
    8354         [ #  # ]:          0 :                         if (ret < 0)
    8355                 :          0 :                                 return ret;
    8356                 :            :                         /* Count all modify-header actions as one action. */
    8357         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8358                 :          0 :                                 ++actions_n;
    8359         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8360                 :            :                                 modify_after_mirror = 1;
    8361                 :          0 :                         tag_id = ((const struct rte_flow_action_set_tag *)
    8362                 :          0 :                                   actions->conf)->index;
    8363                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
    8364                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8365                 :          0 :                         break;
    8366                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
    8367                 :          0 :                         ret = mlx5_flow_validate_action_drop(dev, is_root,
    8368                 :            :                                                              attr, error);
    8369         [ #  # ]:          0 :                         if (ret < 0)
    8370                 :          0 :                                 return ret;
    8371                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
    8372                 :          0 :                         ++actions_n;
    8373                 :          0 :                         break;
    8374                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    8375                 :          0 :                         ret = mlx5_flow_validate_action_queue(actions,
    8376                 :            :                                                               action_flags, dev,
    8377                 :            :                                                               attr, error);
    8378         [ #  # ]:          0 :                         if (ret < 0)
    8379                 :          0 :                                 return ret;
    8380                 :          0 :                         queue_index = ((const struct rte_flow_action_queue *)
    8381                 :          0 :                                                         (actions->conf))->index;
    8382                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
    8383                 :          0 :                         ++actions_n;
    8384                 :          0 :                         break;
    8385                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    8386                 :          0 :                         rss = actions->conf;
    8387                 :          0 :                         ret = mlx5_flow_validate_action_rss(actions,
    8388                 :            :                                                             action_flags, dev,
    8389                 :            :                                                             attr, item_flags,
    8390                 :            :                                                             error);
    8391         [ #  # ]:          0 :                         if (ret < 0)
    8392                 :          0 :                                 return ret;
    8393         [ #  # ]:          0 :                         if (rss && sample_rss &&
    8394         [ #  # ]:          0 :                             (sample_rss->level != rss->level ||
    8395         [ #  # ]:          0 :                             sample_rss->types != rss->types))
    8396                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8397                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8398                 :            :                                         NULL,
    8399                 :            :                                         "Can't use the different RSS types "
    8400                 :            :                                         "or level in the same flow");
    8401   [ #  #  #  # ]:          0 :                         if (rss != NULL && rss->queue_num)
    8402                 :          0 :                                 queue_index = rss->queue[0];
    8403                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
    8404                 :          0 :                         ++actions_n;
    8405                 :          0 :                         break;
    8406                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
    8407                 :            :                         ret =
    8408                 :          0 :                         mlx5_flow_validate_action_default_miss(action_flags,
    8409                 :            :                                         attr, error);
    8410         [ #  # ]:          0 :                         if (ret < 0)
    8411                 :          0 :                                 return ret;
    8412                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
    8413                 :          0 :                         ++actions_n;
    8414                 :          0 :                         break;
    8415                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
    8416                 :            :                         shared_count = true;
    8417                 :            :                         /* fall-through. */
    8418                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    8419                 :          0 :                         ret = flow_dv_validate_action_count(dev, shared_count,
    8420                 :            :                                                             action_flags,
    8421                 :            :                                                             is_root, error);
    8422         [ #  # ]:          0 :                         if (ret < 0)
    8423                 :          0 :                                 return ret;
    8424                 :          0 :                         count = actions->conf;
    8425                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
    8426                 :          0 :                         ++actions_n;
    8427                 :          0 :                         break;
    8428                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    8429         [ #  # ]:          0 :                         if (flow_dv_validate_action_pop_vlan(dev,
    8430                 :            :                                                              action_flags,
    8431                 :            :                                                              actions,
    8432                 :            :                                                              item_flags, attr,
    8433                 :            :                                                              error))
    8434                 :          0 :                                 return -rte_errno;
    8435         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8436                 :            :                                 modify_after_mirror = 1;
    8437                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
    8438                 :          0 :                         ++actions_n;
    8439                 :          0 :                         break;
    8440                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    8441                 :          0 :                         ret = flow_dv_validate_action_push_vlan(dev,
    8442                 :            :                                                                 action_flags,
    8443                 :            :                                                                 vlan_m,
    8444                 :            :                                                                 actions, attr,
    8445                 :            :                                                                 error);
    8446         [ #  # ]:          0 :                         if (ret < 0)
    8447                 :          0 :                                 return ret;
    8448         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8449                 :            :                                 modify_after_mirror = 1;
    8450                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
    8451                 :          0 :                         ++actions_n;
    8452                 :          0 :                         break;
    8453                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    8454                 :          0 :                         ret = flow_dv_validate_action_set_vlan_pcp
    8455                 :            :                                                 (action_flags, actions, error);
    8456         [ #  # ]:          0 :                         if (ret < 0)
    8457                 :          0 :                                 return ret;
    8458         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8459                 :            :                                 modify_after_mirror = 1;
    8460                 :            :                         /* Count PCP with push_vlan command. */
    8461                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;
    8462                 :          0 :                         break;
    8463                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    8464                 :          0 :                         ret = flow_dv_validate_action_set_vlan_vid
    8465                 :            :                                                 (item_flags, action_flags,
    8466                 :            :                                                  actions, error);
    8467         [ #  # ]:          0 :                         if (ret < 0)
    8468                 :          0 :                                 return ret;
    8469         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8470                 :            :                                 modify_after_mirror = 1;
    8471                 :            :                         /* Count VID with push_vlan command. */
    8472                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
    8473                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_VID;
    8474                 :          0 :                         break;
    8475                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    8476                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    8477                 :          0 :                         ret = mlx5_flow_dv_validate_action_l2_encap(dev,
    8478                 :            :                                                                     action_flags,
    8479                 :            :                                                                     actions,
    8480                 :            :                                                                     attr,
    8481                 :            :                                                                     error);
    8482         [ #  # ]:          0 :                         if (ret < 0)
    8483                 :          0 :                                 return ret;
    8484                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
    8485                 :          0 :                         ++actions_n;
    8486                 :          0 :                         break;
    8487                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    8488                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    8489                 :          0 :                         ret = mlx5_flow_dv_validate_action_decap(dev,
    8490                 :            :                                                                  action_flags,
    8491                 :            :                                                                  actions,
    8492                 :            :                                                                  item_flags,
    8493                 :            :                                                                  attr, error);
    8494         [ #  # ]:          0 :                         if (ret < 0)
    8495                 :          0 :                                 return ret;
    8496         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8497                 :            :                                 modify_after_mirror = 1;
    8498                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
    8499                 :          0 :                         ++actions_n;
    8500                 :          0 :                         break;
    8501                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    8502                 :          0 :                         ret = mlx5_flow_dv_validate_action_raw_encap_decap
    8503                 :          0 :                                 (dev, NULL, actions->conf, attr, &action_flags,
    8504                 :            :                                  &actions_n, actions, item_flags, error);
    8505         [ #  # ]:          0 :                         if (ret < 0)
    8506                 :          0 :                                 return ret;
    8507                 :            :                         break;
    8508                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    8509                 :          0 :                         decap = actions->conf;
    8510         [ #  # ]:          0 :                         while ((++actions)->type == RTE_FLOW_ACTION_TYPE_VOID)
    8511                 :            :                                 ;
    8512         [ #  # ]:          0 :                         if (actions->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    8513                 :            :                                 encap = NULL;
    8514                 :            :                                 actions--;
    8515                 :            :                         } else {
    8516                 :          0 :                                 encap = actions->conf;
    8517                 :            :                         }
    8518         [ #  # ]:          0 :                         ret = mlx5_flow_dv_validate_action_raw_encap_decap
    8519                 :            :                                 (dev,
    8520                 :            :                                  decap ? decap : &empty_decap, encap,
    8521                 :            :                                  attr, &action_flags, &actions_n,
    8522                 :            :                                  actions, item_flags, error);
    8523         [ #  # ]:          0 :                         if (ret < 0)
    8524                 :          0 :                                 return ret;
    8525         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) &&
    8526                 :            :                             (action_flags & MLX5_FLOW_ACTION_DECAP))
    8527                 :            :                                 modify_after_mirror = 1;
    8528                 :            :                         break;
    8529                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
    8530                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    8531                 :          0 :                         ret = flow_dv_validate_action_modify_mac(action_flags,
    8532                 :            :                                                                  actions,
    8533                 :            :                                                                  item_flags,
    8534                 :            :                                                                  error);
    8535         [ #  # ]:          0 :                         if (ret < 0)
    8536                 :          0 :                                 return ret;
    8537                 :            :                         /* Count all modify-header actions as one action. */
    8538         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8539                 :          0 :                                 ++actions_n;
    8540                 :          0 :                         action_flags |= actions->type ==
    8541                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
    8542         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_MAC_SRC :
    8543                 :            :                                                 MLX5_FLOW_ACTION_SET_MAC_DST;
    8544         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8545                 :            :                                 modify_after_mirror = 1;
    8546                 :            :                         /*
    8547                 :            :                          * Even if the source and destination MAC addresses have
    8548                 :            :                          * overlap in the header with 4B alignment, the convert
    8549                 :            :                          * function will handle them separately and 4 SW actions
    8550                 :            :                          * will be created. And 2 actions will be added each
    8551                 :            :                          * time no matter how many bytes of address will be set.
    8552                 :            :                          */
    8553                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_MAC;
    8554                 :          0 :                         break;
    8555                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
    8556                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
    8557                 :          0 :                         ret = flow_dv_validate_action_modify_ipv4(action_flags,
    8558                 :            :                                                                   actions,
    8559                 :            :                                                                   item_flags,
    8560                 :            :                                                                   error);
    8561         [ #  # ]:          0 :                         if (ret < 0)
    8562                 :          0 :                                 return ret;
    8563                 :            :                         /* Count all modify-header actions as one action. */
    8564         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8565                 :          0 :                                 ++actions_n;
    8566         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8567                 :            :                                 modify_after_mirror = 1;
    8568                 :          0 :                         action_flags |= actions->type ==
    8569                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
    8570         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_IPV4_SRC :
    8571                 :            :                                                 MLX5_FLOW_ACTION_SET_IPV4_DST;
    8572                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_IPV4;
    8573                 :          0 :                         break;
    8574                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
    8575                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
    8576                 :          0 :                         ret = flow_dv_validate_action_modify_ipv6(action_flags,
    8577                 :            :                                                                   actions,
    8578                 :            :                                                                   item_flags,
    8579                 :            :                                                                   error);
    8580         [ #  # ]:          0 :                         if (ret < 0)
    8581                 :          0 :                                 return ret;
    8582         [ #  # ]:          0 :                         if (item_ipv6_proto == IPPROTO_ICMPV6)
    8583                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8584                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8585                 :            :                                         actions,
    8586                 :            :                                         "Can't change header "
    8587                 :            :                                         "with ICMPv6 proto");
    8588                 :            :                         /* Count all modify-header actions as one action. */
    8589         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8590                 :          0 :                                 ++actions_n;
    8591         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8592                 :            :                                 modify_after_mirror = 1;
    8593                 :          0 :                         action_flags |= actions->type ==
    8594                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
    8595         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_IPV6_SRC :
    8596                 :            :                                                 MLX5_FLOW_ACTION_SET_IPV6_DST;
    8597                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_IPV6;
    8598                 :          0 :                         break;
    8599                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
    8600                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    8601                 :          0 :                         ret = flow_dv_validate_action_modify_tp(action_flags,
    8602                 :            :                                                                 actions,
    8603                 :            :                                                                 item_flags,
    8604                 :            :                                                                 error);
    8605         [ #  # ]:          0 :                         if (ret < 0)
    8606                 :          0 :                                 return ret;
    8607                 :            :                         /* Count all modify-header actions as one action. */
    8608         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8609                 :          0 :                                 ++actions_n;
    8610         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8611                 :            :                                 modify_after_mirror = 1;
    8612                 :          0 :                         action_flags |= actions->type ==
    8613                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
    8614         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_TP_SRC :
    8615                 :            :                                                 MLX5_FLOW_ACTION_SET_TP_DST;
    8616                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_PORT;
    8617                 :          0 :                         break;
    8618                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
    8619                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
    8620                 :          0 :                         ret = flow_dv_validate_action_modify_ttl(action_flags,
    8621                 :            :                                                                  actions,
    8622                 :            :                                                                  item_flags,
    8623                 :            :                                                                  error);
    8624         [ #  # ]:          0 :                         if (ret < 0)
    8625                 :          0 :                                 return ret;
    8626                 :            :                         /* Count all modify-header actions as one action. */
    8627         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8628                 :          0 :                                 ++actions_n;
    8629         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8630                 :            :                                 modify_after_mirror = 1;
    8631                 :          0 :                         action_flags |= actions->type ==
    8632                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TTL ?
    8633         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_TTL :
    8634                 :            :                                                 MLX5_FLOW_ACTION_DEC_TTL;
    8635                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TTL;
    8636                 :          0 :                         break;
    8637                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    8638                 :          0 :                         ret = flow_dv_validate_action_jump(dev, tunnel, actions,
    8639                 :            :                                                            action_flags,
    8640                 :            :                                                            attr, external,
    8641                 :            :                                                            error);
    8642         [ #  # ]:          0 :                         if (ret)
    8643                 :          0 :                                 return ret;
    8644                 :          0 :                         ++actions_n;
    8645                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
    8646                 :          0 :                         break;
    8647                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
    8648                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
    8649                 :          0 :                         ret = flow_dv_validate_action_modify_tcp_seq
    8650                 :            :                                                                 (action_flags,
    8651                 :            :                                                                  actions,
    8652                 :            :                                                                  item_flags,
    8653                 :            :                                                                  error);
    8654         [ #  # ]:          0 :                         if (ret < 0)
    8655                 :          0 :                                 return ret;
    8656                 :            :                         /* Count all modify-header actions as one action. */
    8657         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8658                 :          0 :                                 ++actions_n;
    8659         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8660                 :            :                                 modify_after_mirror = 1;
    8661                 :          0 :                         action_flags |= actions->type ==
    8662                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
    8663         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_INC_TCP_SEQ :
    8664                 :            :                                                 MLX5_FLOW_ACTION_DEC_TCP_SEQ;
    8665                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TCPSEQ;
    8666                 :          0 :                         break;
    8667                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
    8668                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
    8669                 :          0 :                         ret = flow_dv_validate_action_modify_tcp_ack
    8670                 :            :                                                                 (action_flags,
    8671                 :            :                                                                  actions,
    8672                 :            :                                                                  item_flags,
    8673                 :            :                                                                  error);
    8674         [ #  # ]:          0 :                         if (ret < 0)
    8675                 :          0 :                                 return ret;
    8676                 :            :                         /* Count all modify-header actions as one action. */
    8677         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8678                 :          0 :                                 ++actions_n;
    8679         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8680                 :            :                                 modify_after_mirror = 1;
    8681                 :          0 :                         action_flags |= actions->type ==
    8682                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
    8683         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_INC_TCP_ACK :
    8684                 :            :                                                 MLX5_FLOW_ACTION_DEC_TCP_ACK;
    8685                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TCPACK;
    8686                 :          0 :                         break;
    8687                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
    8688                 :            :                         break;
    8689                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
    8690                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
    8691                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8692                 :          0 :                         break;
    8693                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    8694         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    8695                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8696                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8697                 :            :                                                   actions,
    8698                 :            :                                                   "action not supported");
    8699                 :          0 :                         ret = mlx5_flow_validate_action_meter(dev,
    8700                 :            :                                                               action_flags,
    8701                 :            :                                                               item_flags,
    8702                 :            :                                                               actions, attr,
    8703                 :            :                                                               port_id_item,
    8704                 :            :                                                               &def_policy,
    8705                 :            :                                                               error);
    8706         [ #  # ]:          0 :                         if (ret < 0)
    8707                 :          0 :                                 return ret;
    8708                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
    8709         [ #  # ]:          0 :                         if (!def_policy)
    8710                 :          0 :                                 action_flags |=
    8711                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
    8712                 :          0 :                         ++actions_n;
    8713                 :            :                         /* Meter action will add one more TAG action. */
    8714                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8715                 :          0 :                         break;
    8716                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
    8717         [ #  # ]:          0 :                         if (is_root)
    8718                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8719                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8720                 :            :                                                                            NULL,
    8721                 :            :                           "Shared ASO age action is not supported for group 0");
    8722         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_AGE)
    8723                 :          0 :                                 return rte_flow_error_set
    8724                 :            :                                                   (error, EINVAL,
    8725                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION,
    8726                 :            :                                                    NULL,
    8727                 :            :                                                    "duplicate age actions set");
    8728         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8729                 :            :                                 aso_after_sample = 1;
    8730                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    8731                 :          0 :                         ++actions_n;
    8732                 :          0 :                         break;
    8733                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
    8734                 :          0 :                         non_shared_age = actions->conf;
    8735                 :          0 :                         ret = flow_dv_validate_action_age(action_flags,
    8736                 :            :                                                           actions, dev,
    8737                 :            :                                                           error);
    8738         [ #  # ]:          0 :                         if (ret < 0)
    8739                 :          0 :                                 return ret;
    8740                 :            :                         /*
    8741                 :            :                          * Validate the regular AGE action (using counter)
    8742                 :            :                          * mutual exclusion with indirect counter actions.
    8743                 :            :                          */
    8744         [ #  # ]:          0 :                         if (!flow_hit_aso_supported(priv, is_root)) {
    8745         [ #  # ]:          0 :                                 if (shared_count)
    8746                 :          0 :                                         return rte_flow_error_set
    8747                 :            :                                                 (error, EINVAL,
    8748                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8749                 :            :                                                 NULL,
    8750                 :            :                                                 "old age and indirect count combination is not supported");
    8751         [ #  # ]:          0 :                                 if (sample_count)
    8752                 :          0 :                                         return rte_flow_error_set
    8753                 :            :                                                 (error, EINVAL,
    8754                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8755                 :            :                                                 NULL,
    8756                 :            :                                                 "old age action and count must be in the same sub flow");
    8757                 :            :                         } else {
    8758         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8759                 :            :                                         aso_after_sample = 1;
    8760                 :            :                         }
    8761                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    8762                 :          0 :                         ++actions_n;
    8763                 :          0 :                         break;
    8764                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
    8765                 :          0 :                         ret = flow_dv_validate_action_modify_ipv4_dscp
    8766                 :            :                                                          (action_flags,
    8767                 :            :                                                           actions,
    8768                 :            :                                                           item_flags,
    8769                 :            :                                                           error);
    8770         [ #  # ]:          0 :                         if (ret < 0)
    8771                 :          0 :                                 return ret;
    8772                 :            :                         /* Count all modify-header actions as one action. */
    8773         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8774                 :          0 :                                 ++actions_n;
    8775         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8776                 :            :                                 modify_after_mirror = 1;
    8777                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
    8778                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_DSCP;
    8779                 :          0 :                         break;
    8780                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
    8781                 :          0 :                         ret = flow_dv_validate_action_modify_ipv6_dscp
    8782                 :            :                                                                 (action_flags,
    8783                 :            :                                                                  actions,
    8784                 :            :                                                                  item_flags,
    8785                 :            :                                                                  error);
    8786         [ #  # ]:          0 :                         if (ret < 0)
    8787                 :          0 :                                 return ret;
    8788                 :            :                         /* Count all modify-header actions as one action. */
    8789         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8790                 :          0 :                                 ++actions_n;
    8791         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8792                 :            :                                 modify_after_mirror = 1;
    8793                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
    8794                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_DSCP;
    8795                 :          0 :                         break;
    8796                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
    8797                 :          0 :                         ret = flow_dv_validate_action_sample(&action_flags,
    8798                 :            :                                                              &sub_action_flags,
    8799                 :            :                                                              actions, dev,
    8800                 :            :                                                              attr, item_flags,
    8801                 :            :                                                              rss, &sample_rss,
    8802                 :            :                                                              &sample_count,
    8803                 :            :                                                              &fdb_mirror,
    8804                 :            :                                                              &sample_port_id,
    8805                 :            :                                                              is_root,
    8806                 :            :                                                              error);
    8807         [ #  # ]:          0 :                         if (ret < 0)
    8808                 :          0 :                                 return ret;
    8809   [ #  #  #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) &&
    8810                 :          0 :                             tag_id == 0 &&
    8811         [ #  # ]:          0 :                             priv->sh->registers.aso_reg == REG_NON)
    8812                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8813                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8814                 :            :                                         "sample after tag action causes metadata tag index 0 corruption");
    8815                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SAMPLE;
    8816                 :          0 :                         ++actions_n;
    8817                 :          0 :                         break;
    8818                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    8819                 :          0 :                         ret = flow_dv_validate_action_modify_field(dev,
    8820                 :            :                                                                    action_flags,
    8821                 :            :                                                                    actions,
    8822                 :            :                                                                    attr,
    8823                 :            :                                                                    is_root,
    8824                 :            :                                                                    error);
    8825         [ #  # ]:          0 :                         if (ret < 0)
    8826                 :          0 :                                 return ret;
    8827         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8828                 :            :                                 modify_after_mirror = 1;
    8829                 :            :                         /* Count all modify-header actions as one action. */
    8830         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8831                 :          0 :                                 ++actions_n;
    8832                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
    8833                 :          0 :                         rw_act_num += ret;
    8834                 :          0 :                         break;
    8835                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    8836                 :          0 :                         ret = mlx5_flow_dv_validate_action_aso_ct(dev,
    8837                 :            :                                                                   action_flags,
    8838                 :            :                                                                   item_flags,
    8839                 :            :                                                                   is_root,
    8840                 :            :                                                                   error);
    8841         [ #  # ]:          0 :                         if (ret < 0)
    8842                 :          0 :                                 return ret;
    8843         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8844                 :            :                                 aso_after_sample = 1;
    8845                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
    8846                 :          0 :                         break;
    8847                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET:
    8848                 :            :                         /* tunnel offload action was processed before
    8849                 :            :                          * list it here as a supported type
    8850                 :            :                          */
    8851                 :            :                         break;
    8852                 :            : #ifdef HAVE_MLX5DV_DR_ACTION_CREATE_DEST_ROOT_TABLE
    8853                 :            :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
    8854                 :            :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
    8855                 :            :                         ++actions_n;
    8856                 :            :                         break;
    8857                 :            : #endif
    8858                 :          0 :                 default:
    8859                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8860                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8861                 :            :                                                   actions,
    8862                 :            :                                                   "action not supported");
    8863                 :            :                 }
    8864                 :            :         }
    8865                 :            :         /*
    8866                 :            :          * Validate actions in flow rules
    8867                 :            :          * - Explicit decap action is prohibited by the tunnel offload API.
    8868                 :            :          * - Drop action in tunnel steer rule is prohibited by the API.
    8869                 :            :          * - Application cannot use MARK action because it's value can mask
    8870                 :            :          *   tunnel default miss notification.
    8871                 :            :          * - JUMP in tunnel match rule has no support in current PMD
    8872                 :            :          *   implementation.
    8873                 :            :          * - TAG & META are reserved for future uses.
    8874                 :            :          */
    8875         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_TUNNEL_SET) {
    8876                 :            :                 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_DECAP    |
    8877                 :            :                                             MLX5_FLOW_ACTION_MARK     |
    8878                 :            :                                             MLX5_FLOW_ACTION_SET_TAG  |
    8879                 :            :                                             MLX5_FLOW_ACTION_SET_META |
    8880                 :            :                                             MLX5_FLOW_ACTION_DROP;
    8881                 :            : 
    8882         [ #  # ]:          0 :                 if (action_flags & bad_actions_mask)
    8883                 :          0 :                         return rte_flow_error_set
    8884                 :            :                                         (error, EINVAL,
    8885                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8886                 :            :                                         "Invalid RTE action in tunnel "
    8887                 :            :                                         "set decap rule");
    8888         [ #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_ACTION_JUMP))
    8889                 :          0 :                         return rte_flow_error_set
    8890                 :            :                                         (error, EINVAL,
    8891                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8892                 :            :                                         "tunnel set decap rule must terminate "
    8893                 :            :                                         "with JUMP");
    8894         [ #  # ]:          0 :                 if (attr->egress)
    8895                 :          0 :                         return rte_flow_error_set
    8896                 :            :                                         (error, EINVAL,
    8897                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8898                 :            :                                         "tunnel flows for ingress and transfer traffic only");
    8899                 :            :         }
    8900         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_TUNNEL_MATCH) {
    8901                 :            :                 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_JUMP    |
    8902                 :            :                                             MLX5_FLOW_ACTION_MARK    |
    8903                 :            :                                             MLX5_FLOW_ACTION_SET_TAG |
    8904                 :            :                                             MLX5_FLOW_ACTION_SET_META;
    8905                 :            : 
    8906         [ #  # ]:          0 :                 if (action_flags & bad_actions_mask)
    8907                 :          0 :                         return rte_flow_error_set
    8908                 :            :                                         (error, EINVAL,
    8909                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8910                 :            :                                         "Invalid RTE action in tunnel "
    8911                 :            :                                         "set match rule");
    8912                 :            :         }
    8913                 :            :         /*
    8914                 :            :          * Validate the drop action mutual exclusion with other actions.
    8915                 :            :          * Drop action is mutually-exclusive with any other action, except for
    8916                 :            :          * Count/Sample/Age actions.
    8917                 :            :          * Drop action compatibility with tunnel offload was already validated.
    8918                 :            :          */
    8919         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_MATCH |
    8920                 :            :                             MLX5_FLOW_ACTION_TUNNEL_MATCH));
    8921         [ #  # ]:          0 :         else if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
    8922         [ #  # ]:          0 :             (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_DROP_INCLUSIVE_ACTIONS)))
    8923                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    8924                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8925                 :            :                                           "Drop action is mutually-exclusive "
    8926                 :            :                                           "with any other action, except for "
    8927                 :            :                                           "Count/Sample/Age action");
    8928                 :            :         /* Eswitch has few restrictions on using items and actions */
    8929         [ #  # ]:          0 :         if (attr->transfer) {
    8930         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev) &&
    8931         [ #  # ]:          0 :                     action_flags & MLX5_FLOW_ACTION_FLAG)
    8932                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8933                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8934                 :            :                                                   NULL,
    8935                 :            :                                                   "unsupported action FLAG");
    8936         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev) &&
    8937         [ #  # ]:          0 :                     action_flags & MLX5_FLOW_ACTION_MARK)
    8938                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8939                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8940                 :            :                                                   NULL,
    8941                 :            :                                                   "unsupported action MARK");
    8942         [ #  # ]:          0 :                 if (action_flags & MLX5_FLOW_ACTION_QUEUE)
    8943                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8944                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8945                 :            :                                                   NULL,
    8946                 :            :                                                   "unsupported action QUEUE");
    8947         [ #  # ]:          0 :                 if (action_flags & MLX5_FLOW_ACTION_RSS)
    8948                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8949                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8950                 :            :                                                   NULL,
    8951                 :            :                                                   "unsupported action RSS");
    8952         [ #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    8953                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8954                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8955                 :            :                                                   actions,
    8956                 :            :                                                   "no fate action is found");
    8957                 :            :         } else {
    8958   [ #  #  #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_FATE_ACTIONS) && attr->ingress)
    8959                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8960                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8961                 :            :                                                   actions,
    8962                 :            :                                                   "no fate action is found");
    8963                 :            :         }
    8964                 :            :         /*
    8965                 :            :          * Continue validation for Xcap and VLAN actions.
    8966                 :            :          * If hairpin is working in explicit TX rule mode, there is no actions
    8967                 :            :          * splitting and the validation of hairpin ingress flow should be the
    8968                 :            :          * same as other standard flows.
    8969                 :            :          */
    8970         [ #  # ]:          0 :         if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS |
    8971         [ #  # ]:          0 :                              MLX5_FLOW_VLAN_ACTIONS)) &&
    8972   [ #  #  #  # ]:          0 :             (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index) ||
    8973                 :          0 :              ((conf = mlx5_rxq_get_hairpin_conf(dev, queue_index)) != NULL &&
    8974         [ #  # ]:          0 :              conf->tx_explicit != 0))) {
    8975         [ #  # ]:          0 :                 if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
    8976                 :            :                     MLX5_FLOW_XCAP_ACTIONS)
    8977                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8978                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8979                 :            :                                                   NULL, "encap and decap "
    8980                 :            :                                                   "combination aren't supported");
    8981                 :            :                 /* Push VLAN is not supported in ingress except for NICs newer than CX5. */
    8982         [ #  # ]:          0 :                 if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) {
    8983                 :          0 :                         struct mlx5_dev_ctx_shared *sh = priv->sh;
    8984                 :            :                         bool direction_error = false;
    8985                 :            : 
    8986         [ #  # ]:          0 :                         if (attr->transfer) {
    8987         [ #  # ]:          0 :                                 bool fdb_tx = flow_source_vport_representor(priv, act_priv);
    8988                 :          0 :                                 bool is_cx5 = sh->steering_format_version ==
    8989                 :            :                                     MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
    8990                 :            : 
    8991         [ #  # ]:          0 :                                 if (!fdb_tx && is_cx5)
    8992                 :            :                                         direction_error = true;
    8993         [ #  # ]:          0 :                         } else if (attr->ingress) {
    8994                 :            :                                 direction_error = true;
    8995                 :            :                         }
    8996                 :            :                         if (direction_error)
    8997                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8998                 :            :                                                           RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
    8999                 :            :                                                           NULL,
    9000                 :            :                                                           "push VLAN action not supported "
    9001                 :            :                                                           "for ingress");
    9002                 :            :                 }
    9003         [ #  # ]:          0 :                 if (attr->ingress) {
    9004         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    9005                 :          0 :                                 return rte_flow_error_set
    9006                 :            :                                                 (error, ENOTSUP,
    9007                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
    9008                 :            :                                                  NULL, "encap is not supported"
    9009                 :            :                                                  " for ingress traffic");
    9010         [ #  # ]:          0 :                         else if ((action_flags & MLX5_FLOW_VLAN_ACTIONS) ==
    9011                 :            :                                         MLX5_FLOW_VLAN_ACTIONS)
    9012                 :          0 :                                 return rte_flow_error_set
    9013                 :            :                                                 (error, ENOTSUP,
    9014                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
    9015                 :            :                                                  NULL, "no support for "
    9016                 :            :                                                  "multiple VLAN actions");
    9017                 :            :                 }
    9018                 :            :         }
    9019                 :            :         /* Pop VLAN is not supported in egress except for NICs newer than CX5. */
    9020         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_POP_VLAN) {
    9021                 :          0 :                 struct mlx5_dev_ctx_shared *sh = priv->sh;
    9022                 :            :                 bool direction_error = false;
    9023                 :            : 
    9024         [ #  # ]:          0 :                 if (attr->transfer) {
    9025         [ #  # ]:          0 :                         bool fdb_tx = flow_source_vport_representor(priv, act_priv);
    9026                 :          0 :                         bool is_cx5 = sh->steering_format_version ==
    9027                 :            :                                         MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
    9028                 :            : 
    9029         [ #  # ]:          0 :                         if (fdb_tx && is_cx5)
    9030                 :            :                                 direction_error = true;
    9031         [ #  # ]:          0 :                 } else if (attr->egress) {
    9032                 :            :                         direction_error = true;
    9033                 :            :                 }
    9034                 :            :                 if (direction_error)
    9035                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    9036                 :            :                                                 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
    9037                 :            :                                                 NULL,
    9038                 :            :                                                 "pop vlan action not supported for egress");
    9039                 :            :         }
    9040         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY) {
    9041         [ #  # ]:          0 :                 if ((action_flags & (MLX5_FLOW_FATE_ACTIONS &
    9042         [ #  # ]:          0 :                         ~MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)) &&
    9043                 :            :                         attr->ingress)
    9044                 :          0 :                         return rte_flow_error_set
    9045                 :            :                                 (error, ENOTSUP,
    9046                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    9047                 :            :                                 NULL, "fate action not supported for "
    9048                 :            :                                 "meter with policy");
    9049         [ #  # ]:          0 :                 if (attr->egress) {
    9050         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)
    9051                 :          0 :                                 return rte_flow_error_set
    9052                 :            :                                         (error, ENOTSUP,
    9053                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9054                 :            :                                         NULL, "modify header action in egress "
    9055                 :            :                                         "cannot be done before meter action");
    9056         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    9057                 :          0 :                                 return rte_flow_error_set
    9058                 :            :                                         (error, ENOTSUP,
    9059                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9060                 :            :                                         NULL, "encap action in egress "
    9061                 :            :                                         "cannot be done before meter action");
    9062         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
    9063                 :          0 :                                 return rte_flow_error_set
    9064                 :            :                                         (error, ENOTSUP,
    9065                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9066                 :            :                                         NULL, "push vlan action in egress "
    9067                 :            :                                         "cannot be done before meter action");
    9068                 :            :                 }
    9069                 :            :         }
    9070                 :            :         /*
    9071                 :            :          * Only support one ASO action in a single flow rule.
    9072                 :            :          * non-shared AGE + counter will fallback to use HW counter, no ASO hit object.
    9073                 :            :          * Group 0 uses HW counter for AGE too even if no counter action.
    9074                 :            :          */
    9075   [ #  #  #  # ]:          0 :         aso_mask = (action_flags & MLX5_FLOW_ACTION_METER && priv->sh->meter_aso_en) << 2 |
    9076   [ #  #  #  #  :          0 :                    (action_flags & MLX5_FLOW_ACTION_CT && priv->sh->ct_aso_en) << 1 |
                   #  # ]
    9077                 :          0 :                    (action_flags & MLX5_FLOW_ACTION_AGE &&
    9078         [ #  # ]:          0 :                     !(non_shared_age && count) &&
    9079   [ #  #  #  #  :          0 :                     (attr->group || (attr->transfer && priv->fdb_def_rule)) &&
             #  #  #  # ]
    9080         [ #  # ]:          0 :                     priv->sh->flow_hit_aso_en);
    9081         [ #  # ]:          0 :         if (rte_popcount64(aso_mask) > 1)
    9082                 :          0 :                 return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
    9083                 :            :                                           NULL, "unsupported combining AGE, METER, CT ASO actions in a single rule");
    9084                 :            :         /*
    9085                 :            :          * Hairpin flow will add one more TAG action in TX implicit mode.
    9086                 :            :          * In TX explicit mode, there will be no hairpin flow ID.
    9087                 :            :          */
    9088         [ #  # ]:          0 :         if (hairpin > 0)
    9089                 :          0 :                 rw_act_num += MLX5_ACT_NUM_SET_TAG;
    9090                 :            :         /* extra metadata enabled: one more TAG action will be add. */
    9091         [ #  # ]:          0 :         if (dev_conf->dv_flow_en &&
    9092   [ #  #  #  # ]:          0 :             dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    9093                 :          0 :             mlx5_flow_ext_mreg_supported(dev))
    9094                 :          0 :                 rw_act_num += MLX5_ACT_NUM_SET_TAG;
    9095         [ #  # ]:          0 :         if (rw_act_num >
    9096                 :            :                         flow_dv_modify_hdr_action_max(dev, is_root)) {
    9097                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9098                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    9099                 :            :                                           NULL, "too many header modify"
    9100                 :            :                                           " actions to support");
    9101                 :            :         }
    9102         [ #  # ]:          0 :         if (fdb_mirror) {
    9103   [ #  #  #  # ]:          0 :                 if (!priv->sh->cdev->config.hca_attr.reg_c_preserve &&
    9104         [ #  # ]:          0 :                     flow_source_vport_representor(priv, act_priv)) {
    9105                 :            :                         /* Eswitch egress mirror and modify flow has limitation on CX5 */
    9106         [ #  # ]:          0 :                         if (modify_after_mirror)
    9107                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    9108                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9109                 :            :                                                 "sample before modify action is not supported");
    9110         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_JUMP)
    9111                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    9112                 :            :                                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9113                 :            :                                                         "sample and jump action combination is not supported");
    9114                 :            :                 }
    9115         [ #  # ]:          0 :                 if (aso_mask > 0 && aso_after_sample && fdb_mirror)
    9116                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    9117                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9118                 :            :                                                   "sample before ASO action is not supported");
    9119         [ #  # ]:          0 :                 if (sub_action_flags & MLX5_FLOW_ACTION_PORT_ID) {
    9120                 :          0 :                         port_priv = mlx5_port_to_eswitch_info(sample_port_id, false);
    9121         [ #  # ]:          0 :                         if (flow_source_vport_representor(priv, port_priv)) {
    9122         [ #  # ]:          0 :                                 if (sub_action_flags & MLX5_FLOW_ACTION_ENCAP)
    9123                 :          0 :                                         return rte_flow_error_set(error, ENOTSUP,
    9124                 :            :                                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9125                 :            :                                                                 "mirror to rep port with encap is not supported");
    9126                 :            :                         } else {
    9127         [ #  # ]:          0 :                                 if (!(sub_action_flags & MLX5_FLOW_ACTION_ENCAP) &&
    9128         [ #  # ]:          0 :                                     (action_flags & MLX5_FLOW_ACTION_JUMP))
    9129                 :          0 :                                         return rte_flow_error_set(error, ENOTSUP,
    9130                 :            :                                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9131                 :            :                                                                 "mirror to wire port without encap is not supported");
    9132                 :            :                         }
    9133                 :            :                 }
    9134         [ #  # ]:          0 :                 if ((action_flags & MLX5_FLOW_ACTION_PORT_ID) &&
    9135                 :            :                     (action_flags & MLX5_FLOW_ACTION_ENCAP)) {
    9136                 :          0 :                         port_priv = mlx5_port_to_eswitch_info(port_id, false);
    9137         [ #  # ]:          0 :                         if (flow_source_vport_representor(priv, port_priv))
    9138                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    9139                 :            :                                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9140                 :            :                                                         "mirror to rep port with encap is not supported");
    9141                 :            :                 }
    9142                 :            :         }
    9143                 :            :         /*
    9144                 :            :          * Validation the NIC Egress flow on representor, except implicit
    9145                 :            :          * hairpin default egress flow with TX_QUEUE item, other flows not
    9146                 :            :          * work due to metadata regC0 mismatch.
    9147                 :            :          */
    9148   [ #  #  #  #  :          0 :         if (attr->egress && priv->representor && !(item_flags & MLX5_FLOW_ITEM_SQ))
                   #  # ]
    9149                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    9150                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    9151                 :            :                                           NULL,
    9152                 :            :                                           "NIC egress rules on representors"
    9153                 :            :                                           " is not supported");
    9154                 :            :         return 0;
    9155                 :            : }
    9156                 :            : 
    9157                 :            : /**
    9158                 :            :  * Internal preparation function. Allocates the DV flow size,
    9159                 :            :  * this size is constant.
    9160                 :            :  *
    9161                 :            :  * @param[in] dev
    9162                 :            :  *   Pointer to the rte_eth_dev structure.
    9163                 :            :  * @param[in] attr
    9164                 :            :  *   Pointer to the flow attributes.
    9165                 :            :  * @param[in] items
    9166                 :            :  *   Pointer to the list of items.
    9167                 :            :  * @param[in] actions
    9168                 :            :  *   Pointer to the list of actions.
    9169                 :            :  * @param[out] error
    9170                 :            :  *   Pointer to the error structure.
    9171                 :            :  *
    9172                 :            :  * @return
    9173                 :            :  *   Pointer to mlx5_flow object on success,
    9174                 :            :  *   otherwise NULL and rte_errno is set.
    9175                 :            :  */
    9176                 :            : static struct mlx5_flow *
    9177                 :          0 : flow_dv_prepare(struct rte_eth_dev *dev,
    9178                 :            :                 const struct rte_flow_attr *attr __rte_unused,
    9179                 :            :                 const struct rte_flow_item items[] __rte_unused,
    9180                 :            :                 const struct rte_flow_action actions[] __rte_unused,
    9181                 :            :                 struct rte_flow_error *error)
    9182                 :            : {
    9183                 :          0 :         uint32_t handle_idx = 0;
    9184                 :            :         struct mlx5_flow *dev_flow;
    9185                 :            :         struct mlx5_flow_handle *dev_handle;
    9186                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9187                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
    9188                 :            : 
    9189                 :            :         MLX5_ASSERT(wks);
    9190                 :          0 :         wks->skip_matcher_reg = 0;
    9191                 :          0 :         wks->policy = NULL;
    9192                 :          0 :         wks->final_policy = NULL;
    9193                 :          0 :         wks->vport_meta_tag = 0;
    9194                 :            :         /* In case of corrupting the memory. */
    9195         [ #  # ]:          0 :         if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) {
    9196                 :          0 :                 rte_flow_error_set(error, ENOSPC,
    9197                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9198                 :            :                                    "not free temporary device flow");
    9199                 :          0 :                 return NULL;
    9200                 :            :         }
    9201                 :          0 :         dev_handle = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
    9202                 :            :                                    &handle_idx);
    9203         [ #  # ]:          0 :         if (!dev_handle) {
    9204                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9205                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9206                 :            :                                    "not enough memory to create flow handle");
    9207                 :          0 :                 return NULL;
    9208                 :            :         }
    9209                 :            :         MLX5_ASSERT(wks->flow_idx < RTE_DIM(wks->flows));
    9210                 :          0 :         dev_flow = &wks->flows[wks->flow_idx++];
    9211                 :            :         memset(dev_flow, 0, sizeof(*dev_flow));
    9212                 :          0 :         dev_flow->handle = dev_handle;
    9213                 :          0 :         dev_flow->handle_idx = handle_idx;
    9214                 :          0 :         dev_flow->dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);
    9215                 :          0 :         dev_flow->ingress = attr->ingress;
    9216                 :          0 :         dev_flow->dv.transfer = attr->transfer;
    9217                 :          0 :         return dev_flow;
    9218                 :            : }
    9219                 :            : 
    9220                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
    9221                 :            : /**
    9222                 :            :  * Sanity check for match mask and value. Similar to check_valid_spec() in
    9223                 :            :  * kernel driver. If unmasked bit is present in value, it returns failure.
    9224                 :            :  *
    9225                 :            :  * @param match_mask
    9226                 :            :  *   pointer to match mask buffer.
    9227                 :            :  * @param match_value
    9228                 :            :  *   pointer to match value buffer.
    9229                 :            :  *
    9230                 :            :  * @return
    9231                 :            :  *   0 if valid, -EINVAL otherwise.
    9232                 :            :  */
    9233                 :            : static int
    9234                 :            : flow_dv_check_valid_spec(void *match_mask, void *match_value)
    9235                 :            : {
    9236                 :            :         uint8_t *m = match_mask;
    9237                 :            :         uint8_t *v = match_value;
    9238                 :            :         unsigned int i;
    9239                 :            : 
    9240                 :            :         for (i = 0; i < MLX5_ST_SZ_BYTES(fte_match_param); ++i) {
    9241                 :            :                 if (v[i] & ~m[i]) {
    9242                 :            :                         DRV_LOG(ERR,
    9243                 :            :                                 "match_value differs from match_criteria"
    9244                 :            :                                 " %p[%u] != %p[%u]",
    9245                 :            :                                 match_value, i, match_mask, i);
    9246                 :            :                         return -EINVAL;
    9247                 :            :                 }
    9248                 :            :         }
    9249                 :            :         return 0;
    9250                 :            : }
    9251                 :            : #endif
    9252                 :            : 
    9253                 :            : /**
    9254                 :            :  * Add match of ip_version.
    9255                 :            :  *
    9256                 :            :  * @param[in] group
    9257                 :            :  *   Flow group.
    9258                 :            :  * @param[in] headers_v
    9259                 :            :  *   Values header pointer.
    9260                 :            :  * @param[in] headers_m
    9261                 :            :  *   Masks header pointer.
    9262                 :            :  * @param[in] ip_version
    9263                 :            :  *   The IP version to set.
    9264                 :            :  */
    9265                 :            : static inline void
    9266                 :          0 : flow_dv_set_match_ip_version(uint32_t group,
    9267                 :            :                              void *headers_v,
    9268                 :            :                              uint32_t key_type,
    9269                 :            :                              uint8_t ip_version)
    9270                 :            : {
    9271   [ #  #  #  # ]:          0 :         if (group == 0 && (key_type & MLX5_SET_MATCHER_M))
    9272         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 0xf);
    9273                 :            :         else
    9274         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version,
    9275                 :            :                          ip_version);
    9276         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, 0);
    9277                 :          0 : }
    9278                 :            : 
    9279                 :            : /**
    9280                 :            :  * Add Ethernet item to the value.
    9281                 :            :  *
    9282                 :            :  * @param[in, out] key
    9283                 :            :  *   Flow matcher value.
    9284                 :            :  * @param[in] item
    9285                 :            :  *   Flow pattern to translate.
    9286                 :            :  * @param[in] inner
    9287                 :            :  *   Item is inner pattern.
    9288                 :            :  * @param[in] grpup
    9289                 :            :  *   Flow matcher group.
    9290                 :            :  * @param[in] key_type
    9291                 :            :  *   Set flow matcher mask or value.
    9292                 :            :  */
    9293                 :            : static void
    9294                 :          0 : flow_dv_translate_item_eth(void *key, const struct rte_flow_item *item,
    9295                 :            :                            int inner, uint32_t group, uint32_t key_type)
    9296                 :            : {
    9297                 :          0 :         const struct rte_flow_item_eth *eth_vv = item->spec;
    9298                 :            :         const struct rte_flow_item_eth *eth_m;
    9299                 :            :         const struct rte_flow_item_eth *eth_v;
    9300                 :          0 :         const struct rte_flow_item_eth nic_mask = {
    9301                 :            :                 .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    9302                 :            :                 .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    9303                 :            :                 .hdr.ether_type = RTE_BE16(0xffff),
    9304                 :            :                 .has_vlan = 0,
    9305                 :            :         };
    9306                 :            :         void *hdrs_v;
    9307                 :            :         char *l24_v;
    9308                 :            :         unsigned int i;
    9309                 :            : 
    9310   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9311                 :          0 :                 return;
    9312   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, eth_v, eth_m, &nic_mask);
             #  #  #  # ]
    9313         [ #  # ]:          0 :         if (!eth_vv)
    9314                 :            :                 eth_vv = eth_v;
    9315         [ #  # ]:          0 :         if (inner)
    9316                 :          0 :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
    9317                 :            :         else
    9318                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9319                 :            :         /* The value must be in the range of the mask. */
    9320                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, dmac_47_16);
    9321         [ #  # ]:          0 :         for (i = 0; i < sizeof(eth_m->hdr.dst_addr); ++i)
    9322                 :          0 :                 l24_v[i] = eth_m->hdr.dst_addr.addr_bytes[i] & eth_v->hdr.dst_addr.addr_bytes[i];
    9323                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, smac_47_16);
    9324                 :            :         /* The value must be in the range of the mask. */
    9325         [ #  # ]:          0 :         for (i = 0; i < sizeof(eth_m->hdr.dst_addr); ++i)
    9326                 :          0 :                 l24_v[i] = eth_m->hdr.src_addr.addr_bytes[i] & eth_v->hdr.src_addr.addr_bytes[i];
    9327                 :            :         /*
    9328                 :            :          * HW supports match on one Ethertype, the Ethertype following the last
    9329                 :            :          * VLAN tag of the packet (see PRM).
    9330                 :            :          * Set match on ethertype only if ETH header is not followed by VLAN.
    9331                 :            :          * HW is optimized for IPv4/IPv6. In such cases, avoid setting
    9332                 :            :          * ethertype, and use ip_version field instead.
    9333                 :            :          * eCPRI over Ether layer will use type value 0xAEFE.
    9334                 :            :          */
    9335         [ #  # ]:          0 :         if (eth_m->hdr.ether_type == 0xFFFF) {
    9336                 :          0 :                 rte_be16_t type = eth_v->hdr.ether_type;
    9337                 :            : 
    9338                 :            :                 /*
    9339                 :            :                  * When set the matcher mask, refer to the original spec
    9340                 :            :                  * value.
    9341                 :            :                  */
    9342         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M) {
    9343         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9344                 :          0 :                         type = eth_vv->hdr.ether_type;
    9345                 :            :                 }
    9346                 :            :                 /* Set cvlan_tag mask for any single\multi\un-tagged case. */
    9347   [ #  #  #  #  :          0 :                 switch (type) {
                      # ]
    9348                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_VLAN):
    9349         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9350                 :          0 :                         return;
    9351                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_QINQ):
    9352         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9353                 :          0 :                         return;
    9354                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV4):
    9355                 :          0 :                         flow_dv_set_match_ip_version(group, hdrs_v, key_type,
    9356                 :            :                                                      4);
    9357                 :          0 :                         return;
    9358                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV6):
    9359                 :          0 :                         flow_dv_set_match_ip_version(group, hdrs_v, key_type,
    9360                 :            :                                                      6);
    9361                 :          0 :                         return;
    9362                 :            :                 default:
    9363                 :            :                         break;
    9364                 :            :                 }
    9365                 :            :         }
    9366                 :            :         /*
    9367                 :            :          * Only SW steering value should refer to the mask value.
    9368                 :            :          * Other cases are using the fake masks, just ignore the mask.
    9369                 :            :          */
    9370   [ #  #  #  # ]:          0 :         if (eth_v->has_vlan && eth_m->has_vlan) {
    9371                 :            :                 /*
    9372                 :            :                  * Here, when also has_more_vlan field in VLAN item is
    9373                 :            :                  * not set, only single-tagged packets will be matched.
    9374                 :            :                  */
    9375         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9376   [ #  #  #  # ]:          0 :                 if (key_type != MLX5_SET_MATCHER_HS_M && eth_vv->has_vlan)
    9377                 :            :                         return;
    9378                 :            :         }
    9379                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
    9380                 :          0 :         *(uint16_t *)(l24_v) = eth_m->hdr.ether_type & eth_v->hdr.ether_type;
    9381                 :            : }
    9382                 :            : 
    9383                 :            : /**
    9384                 :            :  * Add VLAN item to the value.
    9385                 :            :  *
    9386                 :            :  * @param[in, out] key
    9387                 :            :  *   Flow matcher value.
    9388                 :            :  * @param[in] item
    9389                 :            :  *   Flow pattern to translate.
    9390                 :            :  * @param[in] inner
    9391                 :            :  *   Item is inner pattern.
    9392                 :            :  * @param[in] wks
    9393                 :            :  *   Item workspace.
    9394                 :            :  * @param[in] key_type
    9395                 :            :  *   Set flow matcher mask or value.
    9396                 :            :  */
    9397                 :            : static void
    9398                 :          0 : flow_dv_translate_item_vlan(void *key, const struct rte_flow_item *item,
    9399                 :            :                             int inner, struct mlx5_dv_matcher_workspace *wks,
    9400                 :            :                             uint32_t key_type)
    9401                 :            : {
    9402                 :            :         const struct rte_flow_item_vlan *vlan_m;
    9403                 :            :         const struct rte_flow_item_vlan *vlan_v;
    9404                 :          0 :         const struct rte_flow_item_vlan *vlan_vv = item->spec;
    9405                 :            :         void *hdrs_v;
    9406                 :            :         uint16_t tci_v;
    9407                 :            : 
    9408         [ #  # ]:          0 :         if (inner) {
    9409                 :          0 :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
    9410                 :            :         } else {
    9411                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9412                 :            :                 /*
    9413                 :            :                  * This is workaround, masks are not supported,
    9414                 :            :                  * and pre-validated.
    9415                 :            :                  */
    9416         [ #  # ]:          0 :                 if (vlan_vv)
    9417         [ #  # ]:          0 :                         wks->vlan_tag = rte_be_to_cpu_16(vlan_vv->hdr.vlan_tci) & 0x0fff;
    9418                 :            :         }
    9419                 :            :         /*
    9420                 :            :          * When VLAN item exists in flow, mark packet as tagged,
    9421                 :            :          * even if TCI is not specified.
    9422                 :            :          */
    9423   [ #  #  #  # ]:          0 :         if (!MLX5_GET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag))
    9424         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9425   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9426                 :            :                 return;
    9427   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, vlan_v, vlan_m,
             #  #  #  # ]
    9428                 :            :                          &rte_flow_item_vlan_mask);
    9429         [ #  # ]:          0 :         tci_v = rte_be_to_cpu_16(vlan_m->hdr.vlan_tci & vlan_v->hdr.vlan_tci);
    9430         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_vid, tci_v);
    9431         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_cfi, tci_v >> 12);
    9432         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_prio, tci_v >> 13);
    9433                 :            :         /*
    9434                 :            :          * HW is optimized for IPv4/IPv6. In such cases, avoid setting
    9435                 :            :          * ethertype, and use ip_version field instead.
    9436                 :            :          */
    9437         [ #  # ]:          0 :         if (vlan_m->hdr.eth_proto == 0xFFFF) {
    9438                 :          0 :                 rte_be16_t inner_type = vlan_v->hdr.eth_proto;
    9439                 :            : 
    9440                 :            :                 /*
    9441                 :            :                  * When set the matcher mask, refer to the original spec
    9442                 :            :                  * value.
    9443                 :            :                  */
    9444         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M)
    9445                 :          0 :                         inner_type = vlan_vv->hdr.eth_proto;
    9446   [ #  #  #  # ]:          0 :                 switch (inner_type) {
    9447                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_VLAN):
    9448         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9449         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_V)
    9450         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
    9451                 :            :                                          cvlan_tag, 0);
    9452                 :          0 :                         return;
    9453                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV4):
    9454                 :          0 :                         flow_dv_set_match_ip_version
    9455                 :            :                                 (wks->group, hdrs_v, key_type, 4);
    9456                 :          0 :                         return;
    9457                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV6):
    9458                 :          0 :                         flow_dv_set_match_ip_version
    9459                 :            :                                 (wks->group, hdrs_v, key_type, 6);
    9460                 :          0 :                         return;
    9461                 :            :                 default:
    9462                 :            :                         break;
    9463                 :            :                 }
    9464                 :            :         }
    9465   [ #  #  #  # ]:          0 :         if (vlan_m->has_more_vlan && vlan_v->has_more_vlan) {
    9466         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9467                 :            :                 /* Only one vlan_tag bit can be set. */
    9468         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_V)
    9469         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0);
    9470                 :          0 :                 return;
    9471                 :            :         }
    9472   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, ethertype,
    9473                 :            :                  rte_be_to_cpu_16(vlan_m->hdr.eth_proto & vlan_v->hdr.eth_proto));
    9474                 :            : }
    9475                 :            : 
    9476                 :            : /**
    9477                 :            :  * Add IPV4 item to the value.
    9478                 :            :  *
    9479                 :            :  * @param[in, out] key
    9480                 :            :  *   Flow matcher value.
    9481                 :            :  * @param[in] item
    9482                 :            :  *   Flow pattern to translate.
    9483                 :            :  * @param[in] inner
    9484                 :            :  *   Item is inner pattern.
    9485                 :            :  * @param[in] group
    9486                 :            :  *   The group to insert the rule.
    9487                 :            :  * @param[in] key_type
    9488                 :            :  *   Set flow matcher mask or value.
    9489                 :            :  */
    9490                 :            : static void
    9491                 :          0 : flow_dv_translate_item_ipv4(void *key, const struct rte_flow_item *item,
    9492                 :            :                             int inner, uint32_t group, uint32_t key_type)
    9493                 :            : {
    9494                 :            :         const struct rte_flow_item_ipv4 *ipv4_m;
    9495                 :            :         const struct rte_flow_item_ipv4 *ipv4_v;
    9496                 :          0 :         const struct rte_flow_item_ipv4 nic_mask = {
    9497                 :            :                 .hdr = {
    9498                 :            :                         .src_addr = RTE_BE32(0xffffffff),
    9499                 :            :                         .dst_addr = RTE_BE32(0xffffffff),
    9500                 :            :                         .type_of_service = 0xff,
    9501                 :            :                         .next_proto_id = 0xff,
    9502                 :            :                         .time_to_live = 0xff,
    9503                 :            :                 },
    9504                 :            :         };
    9505                 :            :         void *headers_v;
    9506                 :            :         char *l24_v;
    9507                 :            :         uint8_t tos;
    9508                 :            : 
    9509         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9510                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9511                 :          0 :         flow_dv_set_match_ip_version(group, headers_v, key_type, 4);
    9512   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9513                 :          0 :                 return;
    9514   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv4_v, ipv4_m, &nic_mask);
             #  #  #  # ]
    9515                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9516                 :            :                              dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
    9517                 :          0 :         *(uint32_t *)l24_v = ipv4_m->hdr.dst_addr & ipv4_v->hdr.dst_addr;
    9518                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9519                 :            :                           src_ipv4_src_ipv6.ipv4_layout.ipv4);
    9520                 :          0 :         *(uint32_t *)l24_v = ipv4_m->hdr.src_addr & ipv4_v->hdr.src_addr;
    9521                 :          0 :         tos = ipv4_m->hdr.type_of_service & ipv4_v->hdr.type_of_service;
    9522         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ipv4_ihl,
    9523                 :            :                  ipv4_v->hdr.ihl & ipv4_m->hdr.ihl);
    9524         [ #  # ]:          0 :         if (key_type == MLX5_SET_MATCHER_SW_M)
    9525         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
    9526                 :            :                          ipv4_v->hdr.type_of_service);
    9527         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, tos);
    9528         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, tos >> 2);
    9529         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9530                 :            :                  ipv4_v->hdr.next_proto_id & ipv4_m->hdr.next_proto_id);
    9531         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit,
    9532                 :            :                  ipv4_v->hdr.time_to_live & ipv4_m->hdr.time_to_live);
    9533         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
    9534                 :            :                  !!(ipv4_v->hdr.fragment_offset & ipv4_m->hdr.fragment_offset));
    9535                 :            : }
    9536                 :            : 
    9537                 :            : /**
    9538                 :            :  * Add IPV6 item to the value.
    9539                 :            :  *
    9540                 :            :  * @param[in, out] key
    9541                 :            :  *   Flow matcher value.
    9542                 :            :  * @param[in] item
    9543                 :            :  *   Flow pattern to translate.
    9544                 :            :  * @param[in] inner
    9545                 :            :  *   Item is inner pattern.
    9546                 :            :  * @param[in] group
    9547                 :            :  *   The group to insert the rule.
    9548                 :            :  * @param[in] key_type
    9549                 :            :  *   Set flow matcher mask or value.
    9550                 :            :  */
    9551                 :            : static void
    9552                 :          0 : flow_dv_translate_item_ipv6(void *key, const struct rte_flow_item *item,
    9553                 :            :                             int inner, uint32_t group, uint32_t key_type)
    9554                 :            : {
    9555                 :            :         const struct rte_flow_item_ipv6 *ipv6_m;
    9556                 :            :         const struct rte_flow_item_ipv6 *ipv6_v;
    9557                 :          0 :         const struct rte_flow_item_ipv6 nic_mask = {
    9558                 :            :                 .hdr = {
    9559                 :            :                         .src_addr = RTE_IPV6_MASK_FULL,
    9560                 :            :                         .dst_addr = RTE_IPV6_MASK_FULL,
    9561                 :            :                         .vtc_flow = RTE_BE32(0xffffffff),
    9562                 :            :                         .proto = 0xff,
    9563                 :            :                         .hop_limits = 0xff,
    9564                 :            :                 },
    9565                 :            :         };
    9566                 :            :         void *headers_v;
    9567                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9568                 :            :         char *l24_v;
    9569                 :            :         uint32_t vtc_v;
    9570                 :            :         int i;
    9571                 :            :         int size;
    9572                 :            : 
    9573         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9574                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9575                 :          0 :         flow_dv_set_match_ip_version(group, headers_v, key_type, 6);
    9576   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9577                 :          0 :                 return;
    9578   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv6_v, ipv6_m, &nic_mask);
             #  #  #  # ]
    9579                 :            :         size = sizeof(ipv6_m->hdr.dst_addr);
    9580                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9581                 :            :                              dst_ipv4_dst_ipv6.ipv6_layout.ipv6);
    9582         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9583                 :          0 :                 l24_v[i] = ipv6_m->hdr.dst_addr.a[i] & ipv6_v->hdr.dst_addr.a[i];
    9584                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9585                 :            :                              src_ipv4_src_ipv6.ipv6_layout.ipv6);
    9586         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9587                 :          0 :                 l24_v[i] = ipv6_m->hdr.src_addr.a[i] & ipv6_v->hdr.src_addr.a[i];
    9588                 :            :         /* TOS. */
    9589         [ #  # ]:          0 :         vtc_v = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow & ipv6_v->hdr.vtc_flow);
    9590         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, vtc_v >> 20);
    9591         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, vtc_v >> 22);
    9592                 :            :         /* Label. */
    9593         [ #  # ]:          0 :         if (inner)
    9594         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc, misc_v, inner_ipv6_flow_label,
    9595                 :            :                          vtc_v);
    9596                 :            :         else
    9597         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc, misc_v, outer_ipv6_flow_label,
    9598                 :            :                          vtc_v);
    9599                 :            :         /* Protocol. */
    9600         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9601                 :            :                  ipv6_v->hdr.proto & ipv6_m->hdr.proto);
    9602                 :            :         /* Hop limit. */
    9603         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit,
    9604                 :            :                  ipv6_v->hdr.hop_limits & ipv6_m->hdr.hop_limits);
    9605         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
    9606                 :            :                  !!(ipv6_v->has_frag_ext & ipv6_m->has_frag_ext));
    9607                 :            : }
    9608                 :            : 
    9609                 :            : /**
    9610                 :            :  * Add IPV6 fragment extension item to the value.
    9611                 :            :  *
    9612                 :            :  * @param[in, out] key
    9613                 :            :  *   Flow matcher value.
    9614                 :            :  * @param[in] item
    9615                 :            :  *   Flow pattern to translate.
    9616                 :            :  * @param[in] inner
    9617                 :            :  *   Item is inner pattern.
    9618                 :            :  * @param[in] key_type
    9619                 :            :  *   Set flow matcher mask or value.
    9620                 :            :  */
    9621                 :            : static void
    9622                 :          0 : flow_dv_translate_item_ipv6_frag_ext(void *key,
    9623                 :            :                                      const struct rte_flow_item *item,
    9624                 :            :                                      int inner, uint32_t key_type)
    9625                 :            : {
    9626                 :            :         const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_m;
    9627                 :            :         const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_v;
    9628                 :          0 :         const struct rte_flow_item_ipv6_frag_ext nic_mask = {
    9629                 :            :                 .hdr = {
    9630                 :            :                         .next_header = 0xff,
    9631                 :            :                         .frag_data = RTE_BE16(0xffff),
    9632                 :            :                 },
    9633                 :            :         };
    9634                 :            :         void *headers_v;
    9635                 :            : 
    9636         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9637                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9638                 :            :         /* IPv6 fragment extension item exists, so packet is IP fragment. */
    9639         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 1);
    9640   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9641                 :          0 :                 return;
    9642   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv6_frag_ext_v,
             #  #  #  # ]
    9643                 :            :                          ipv6_frag_ext_m, &nic_mask);
    9644         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9645                 :            :                  ipv6_frag_ext_v->hdr.next_header &
    9646                 :            :                  ipv6_frag_ext_m->hdr.next_header);
    9647                 :            : }
    9648                 :            : 
    9649                 :            : /**
    9650                 :            :  * Add TCP item to the value.
    9651                 :            :  *
    9652                 :            :  * @param[in, out] key
    9653                 :            :  *   Flow matcher value.
    9654                 :            :  * @param[in] item
    9655                 :            :  *   Flow pattern to translate.
    9656                 :            :  * @param[in] inner
    9657                 :            :  *   Item is inner pattern.
    9658                 :            :  * @param[in] key_type
    9659                 :            :  *   Set flow matcher mask or value.
    9660                 :            :  */
    9661                 :            : static void
    9662                 :          0 : flow_dv_translate_item_tcp(void *key, const struct rte_flow_item *item,
    9663                 :            :                            int inner, uint32_t key_type)
    9664                 :            : {
    9665                 :            :         const struct rte_flow_item_tcp *tcp_m;
    9666                 :            :         const struct rte_flow_item_tcp *tcp_v;
    9667                 :            :         void *headers_v;
    9668                 :            : 
    9669         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9670                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9671         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9672         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9673                 :            :                          ip_protocol, 0xff);
    9674                 :            :         else
    9675         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9676                 :            :                          ip_protocol, IPPROTO_TCP);
    9677   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9678                 :            :                 return;
    9679   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, tcp_v, tcp_m,
             #  #  #  # ]
    9680                 :            :                          &rte_flow_item_tcp_mask);
    9681   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,
    9682                 :            :                  rte_be_to_cpu_16(tcp_v->hdr.src_port & tcp_m->hdr.src_port));
    9683   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,
    9684                 :            :                  rte_be_to_cpu_16(tcp_v->hdr.dst_port & tcp_m->hdr.dst_port));
    9685         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
    9686                 :            :                  tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags);
    9687                 :            : }
    9688                 :            : 
    9689                 :            : /**
    9690                 :            :  * Add ESP item to the value.
    9691                 :            :  *
    9692                 :            :  * @param[in, out] key
    9693                 :            :  *   Flow matcher value.
    9694                 :            :  * @param[in] item
    9695                 :            :  *   Flow pattern to translate.
    9696                 :            :  * @param[in] inner
    9697                 :            :  *   Item is inner pattern.
    9698                 :            :  * @param[in] key_type
    9699                 :            :  *   Set flow matcher mask or value.
    9700                 :            :  */
    9701                 :            : static void
    9702                 :          0 : flow_dv_translate_item_esp(void *key, const struct rte_flow_item *item,
    9703                 :            :                            int inner, uint32_t key_type)
    9704                 :            : {
    9705                 :            :         const struct rte_flow_item_esp *esp_m;
    9706                 :            :         const struct rte_flow_item_esp *esp_v;
    9707                 :            :         void *headers_v;
    9708                 :            :         char *spi_v;
    9709                 :            : 
    9710         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9711                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9712         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9713         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9714                 :            :                          ip_protocol, 0xff);
    9715                 :            :         else
    9716         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9717                 :            :                          ip_protocol, IPPROTO_ESP);
    9718   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9719                 :            :                 return;
    9720   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, esp_v, esp_m,
             #  #  #  # ]
    9721                 :            :                          &rte_flow_item_esp_mask);
    9722                 :            :         headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9723                 :            :         spi_v = inner ? MLX5_ADDR_OF(fte_match_set_misc, headers_v,
    9724         [ #  # ]:          0 :                                 inner_esp_spi) : MLX5_ADDR_OF(fte_match_set_misc
    9725                 :            :                                 , headers_v, outer_esp_spi);
    9726                 :          0 :         *(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
    9727                 :            : }
    9728                 :            : 
    9729                 :            : /**
    9730                 :            :  * Add UDP item to the value.
    9731                 :            :  *
    9732                 :            :  * @param[in, out] key
    9733                 :            :  *   Flow matcher value.
    9734                 :            :  * @param[in] item
    9735                 :            :  *   Flow pattern to translate.
    9736                 :            :  * @param[in] inner
    9737                 :            :  *   Item is inner pattern.
    9738                 :            :  * @param[in] key_type
    9739                 :            :  *   Set flow matcher mask or value.
    9740                 :            :  */
    9741                 :            : static void
    9742                 :          0 : flow_dv_translate_item_udp(void *key, const struct rte_flow_item *item,
    9743                 :            :                            int inner, struct mlx5_dv_matcher_workspace *wks,
    9744                 :            :                            uint32_t key_type)
    9745                 :            : {
    9746                 :            :         const struct rte_flow_item_udp *udp_m;
    9747                 :            :         const struct rte_flow_item_udp *udp_v;
    9748                 :            :         void *headers_v;
    9749                 :            : 
    9750         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9751                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9752         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9753         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9754                 :            :                          ip_protocol, 0xff);
    9755                 :            :         else
    9756         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9757                 :            :                          ip_protocol, IPPROTO_UDP);
    9758   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9759                 :            :                 return;
    9760   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, udp_v, udp_m,
             #  #  #  # ]
    9761                 :            :                          &rte_flow_item_udp_mask);
    9762   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
    9763                 :            :                  rte_be_to_cpu_16(udp_v->hdr.src_port & udp_m->hdr.src_port));
    9764   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
    9765                 :            :                  rte_be_to_cpu_16(udp_v->hdr.dst_port & udp_m->hdr.dst_port));
    9766                 :            :         /* Force get UDP dport in case to be used in VXLAN translate. */
    9767         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW) {
    9768                 :          0 :                 udp_v = item->spec;
    9769         [ #  # ]:          0 :                 wks->udp_dport = rte_be_to_cpu_16(udp_v->hdr.dst_port &
    9770                 :            :                                                   udp_m->hdr.dst_port);
    9771                 :            :         }
    9772                 :            : }
    9773                 :            : 
    9774                 :            : /**
    9775                 :            :  * Add GRE optional Key item to the value.
    9776                 :            :  *
    9777                 :            :  * @param[in, out] key
    9778                 :            :  *   Flow matcher value.
    9779                 :            :  * @param[in] item
    9780                 :            :  *   Flow pattern to translate.
    9781                 :            :  * @param[in] inner
    9782                 :            :  *   Item is inner pattern.
    9783                 :            :  */
    9784                 :            : static void
    9785                 :          0 : flow_dv_translate_item_gre_key(void *key, const struct rte_flow_item *item,
    9786                 :            :                                uint32_t key_type)
    9787                 :            : {
    9788                 :            :         const rte_be32_t *key_m;
    9789                 :            :         const rte_be32_t *key_v;
    9790                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9791                 :          0 :         rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
    9792                 :            : 
    9793                 :            :         /* GRE K bit must be on and should already be validated */
    9794         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
    9795   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9796                 :          0 :                 return;
    9797   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, key_v, key_m,
             #  #  #  # ]
    9798                 :            :                          &gre_key_default_mask);
    9799   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_key_h,
    9800                 :            :                  rte_be_to_cpu_32((*key_v) & (*key_m)) >> 8);
    9801   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_key_l,
    9802                 :            :                  rte_be_to_cpu_32((*key_v) & (*key_m)) & 0xFF);
    9803                 :            : }
    9804                 :            : 
    9805                 :            : /**
    9806                 :            :  * Add GRE item to the value.
    9807                 :            :  *
    9808                 :            :  * @param[in, out] key
    9809                 :            :  *   Flow matcher value.
    9810                 :            :  * @param[in] item
    9811                 :            :  *   Flow pattern to translate.
    9812                 :            :  * @param[in] pattern_flags
    9813                 :            :  *   Accumulated pattern flags.
    9814                 :            :  * @param[in] key_type
    9815                 :            :  *   Set flow matcher mask or value.
    9816                 :            :  */
    9817                 :            : static void
    9818                 :          0 : flow_dv_translate_item_gre(void *key, const struct rte_flow_item *item,
    9819                 :            :                            uint64_t pattern_flags, uint32_t key_type)
    9820                 :            : {
    9821                 :            :         static const struct rte_flow_item_gre empty_gre = {0,};
    9822                 :          0 :         const struct rte_flow_item_gre *gre_m = item->mask;
    9823                 :          0 :         const struct rte_flow_item_gre *gre_v = item->spec;
    9824                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9825                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9826                 :            :         struct {
    9827                 :            :                 union {
    9828                 :            :                         __extension__
    9829                 :            :                         struct {
    9830                 :            :                                 uint16_t version:3;
    9831                 :            :                                 uint16_t rsvd0:9;
    9832                 :            :                                 uint16_t s_present:1;
    9833                 :            :                                 uint16_t k_present:1;
    9834                 :            :                                 uint16_t rsvd_bit1:1;
    9835                 :            :                                 uint16_t c_present:1;
    9836                 :            :                         };
    9837                 :            :                         uint16_t value;
    9838                 :            :                 };
    9839                 :            :         } gre_crks_rsvd0_ver_m, gre_crks_rsvd0_ver_v;
    9840                 :            :         uint16_t protocol_m, protocol_v;
    9841                 :            : 
    9842         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
    9843         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xff);
    9844         [ #  # ]:          0 :                 if (!gre_m)
    9845                 :            :                         gre_m = &rte_flow_item_gre_mask;
    9846                 :            :                 gre_v = gre_m;
    9847                 :            :         } else {
    9848         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9849                 :            :                          IPPROTO_GRE);
    9850         [ #  # ]:          0 :                 if (!gre_v) {
    9851                 :            :                         gre_v = &empty_gre;
    9852                 :            :                         gre_m = &empty_gre;
    9853         [ #  # ]:          0 :                 } else if (!gre_m) {
    9854                 :            :                         gre_m = &rte_flow_item_gre_mask;
    9855                 :            :                 }
    9856         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_HS_V)
    9857                 :            :                         gre_m = gre_v;
    9858                 :            :         }
    9859         [ #  # ]:          0 :         gre_crks_rsvd0_ver_m.value = rte_be_to_cpu_16(gre_m->c_rsvd0_ver);
    9860         [ #  # ]:          0 :         gre_crks_rsvd0_ver_v.value = rte_be_to_cpu_16(gre_v->c_rsvd0_ver);
    9861         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_c_present,
    9862                 :            :                  gre_crks_rsvd0_ver_v.c_present &
    9863                 :            :                  gre_crks_rsvd0_ver_m.c_present);
    9864         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_k_present,
    9865                 :            :                  gre_crks_rsvd0_ver_v.k_present &
    9866                 :            :                  gre_crks_rsvd0_ver_m.k_present);
    9867         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_s_present,
    9868                 :            :                  gre_crks_rsvd0_ver_v.s_present &
    9869                 :            :                  gre_crks_rsvd0_ver_m.s_present);
    9870         [ #  # ]:          0 :         protocol_m = rte_be_to_cpu_16(gre_m->protocol);
    9871         [ #  # ]:          0 :         protocol_v = rte_be_to_cpu_16(gre_v->protocol);
    9872         [ #  # ]:          0 :         if (!protocol_m) {
    9873                 :            :                 /* Force next protocol to prevent matchers duplication */
    9874                 :            :                 protocol_v = mlx5_translate_tunnel_etypes(pattern_flags);
    9875                 :            :                 if (protocol_v)
    9876                 :            :                         protocol_m = 0xFFFF;
    9877                 :            :                 /* Restore the value to mask in mask case. */
    9878         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
    9879                 :            :                         protocol_v = protocol_m;
    9880                 :            :         }
    9881         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_protocol,
    9882                 :            :                  protocol_m & protocol_v);
    9883                 :          0 : }
    9884                 :            : 
    9885                 :            : /**
    9886                 :            :  * Add GRE optional items to the value.
    9887                 :            :  *
    9888                 :            :  * @param[in, out] key
    9889                 :            :  *   Flow matcher value.
    9890                 :            :  * @param[in] item
    9891                 :            :  *   Flow pattern to translate.
    9892                 :            :  * @param[in] gre_item
    9893                 :            :  *   Pointer to gre_item.
    9894                 :            :  * @param[in] pattern_flags
    9895                 :            :  *   Accumulated pattern flags.
    9896                 :            :  * @param[in] key_type
    9897                 :            :  *   Set flow matcher mask or value.
    9898                 :            :  */
    9899                 :            : static void
    9900                 :          0 : flow_dv_translate_item_gre_option(void *key,
    9901                 :            :                                   const struct rte_flow_item *item,
    9902                 :            :                                   const struct rte_flow_item *gre_item,
    9903                 :            :                                   uint64_t pattern_flags, uint32_t key_type)
    9904                 :            : {
    9905                 :            :         void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
    9906                 :          0 :         const struct rte_flow_item_gre_opt *option_m = item->mask;
    9907                 :          0 :         const struct rte_flow_item_gre_opt *option_v = item->spec;
    9908                 :          0 :         const struct rte_flow_item_gre *gre_m = gre_item->mask;
    9909                 :          0 :         const struct rte_flow_item_gre *gre_v = gre_item->spec;
    9910                 :            :         static const struct rte_flow_item_gre empty_gre = {0};
    9911                 :            :         struct rte_flow_item gre_key_item;
    9912                 :            :         uint16_t c_rsvd0_ver_m, c_rsvd0_ver_v;
    9913                 :            :         uint16_t protocol_m, protocol_v;
    9914                 :            : 
    9915                 :            :         /*
    9916                 :            :          * If only match key field, keep using misc for matching.
    9917                 :            :          * If need to match checksum or sequence, using misc5 and do
    9918                 :            :          * not need using misc.
    9919                 :            :          */
    9920         [ #  # ]:          0 :         if (!(option_m->sequence.sequence ||
    9921         [ #  # ]:          0 :               option_m->checksum_rsvd.checksum)) {
    9922                 :          0 :                 flow_dv_translate_item_gre(key, gre_item, pattern_flags, key_type);
    9923                 :          0 :                 gre_key_item.spec = &option_v->key.key;
    9924                 :          0 :                 gre_key_item.mask = &option_m->key.key;
    9925                 :          0 :                 flow_dv_translate_item_gre_key(key, &gre_key_item, key_type);
    9926                 :          0 :                 return;
    9927                 :            :         }
    9928         [ #  # ]:          0 :         if (!gre_v) {
    9929                 :            :                 gre_v = &empty_gre;
    9930                 :            :                 gre_m = &empty_gre;
    9931                 :            :         } else {
    9932         [ #  # ]:          0 :                 if (!gre_m)
    9933                 :            :                         gre_m = &rte_flow_item_gre_mask;
    9934                 :            :         }
    9935                 :          0 :         protocol_v = gre_v->protocol;
    9936                 :          0 :         protocol_m = gre_m->protocol;
    9937         [ #  # ]:          0 :         if (!protocol_m) {
    9938                 :            :                 /* Force next protocol to prevent matchers duplication */
    9939                 :            :                 uint16_t ether_type =
    9940                 :            :                         mlx5_translate_tunnel_etypes(pattern_flags);
    9941                 :            :                 if (ether_type) {
    9942         [ #  # ]:          0 :                         protocol_v = rte_be_to_cpu_16(ether_type);
    9943                 :            :                         protocol_m = UINT16_MAX;
    9944                 :            :                 }
    9945                 :            :         }
    9946                 :          0 :         c_rsvd0_ver_v = gre_v->c_rsvd0_ver;
    9947                 :          0 :         c_rsvd0_ver_m = gre_m->c_rsvd0_ver;
    9948         [ #  # ]:          0 :         if (option_m->sequence.sequence) {
    9949                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x1000);
    9950                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x1000);
    9951                 :            :         }
    9952         [ #  # ]:          0 :         if (option_m->key.key) {
    9953                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x2000);
    9954                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x2000);
    9955                 :            :         }
    9956         [ #  # ]:          0 :         if (option_m->checksum_rsvd.checksum) {
    9957                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x8000);
    9958                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x8000);
    9959                 :            :         }
    9960         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
    9961                 :            :                 c_rsvd0_ver_v = c_rsvd0_ver_m;
    9962                 :            :                 protocol_v = protocol_m;
    9963                 :            :                 option_v = option_m;
    9964                 :            :         }
    9965                 :            :         /*
    9966                 :            :          * Hardware parses GRE optional field into the fixed location,
    9967                 :            :          * do not need to adjust the tunnel dword indices.
    9968                 :            :          */
    9969   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0,
    9970                 :            :                  rte_be_to_cpu_32((c_rsvd0_ver_v | protocol_v << 16) &
    9971                 :            :                                   (c_rsvd0_ver_m | protocol_m << 16)));
    9972   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1,
    9973                 :            :                  rte_be_to_cpu_32(option_v->checksum_rsvd.checksum &
    9974                 :            :                                   option_m->checksum_rsvd.checksum));
    9975   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_2,
    9976                 :            :                  rte_be_to_cpu_32(option_v->key.key & option_m->key.key));
    9977   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_3,
    9978                 :            :                  rte_be_to_cpu_32(option_v->sequence.sequence &
    9979                 :            :                                   option_m->sequence.sequence));
    9980                 :            : }
    9981                 :            : 
    9982                 :            : /**
    9983                 :            :  * Add NVGRE item to matcher and to the value.
    9984                 :            :  *
    9985                 :            :  * @param[in, out] key
    9986                 :            :  *   Flow matcher value.
    9987                 :            :  * @param[in] item
    9988                 :            :  *   Flow pattern to translate.
    9989                 :            :  * @param[in] pattern_flags
    9990                 :            :  *   Accumulated pattern flags.
    9991                 :            :  * @param[in] key_type
    9992                 :            :  *   Set flow matcher mask or value.
    9993                 :            :  */
    9994                 :            : static void
    9995                 :          0 : flow_dv_translate_item_nvgre(void *key, const struct rte_flow_item *item,
    9996                 :            :                              unsigned long pattern_flags, uint32_t key_type)
    9997                 :            : {
    9998                 :            :         const struct rte_flow_item_nvgre *nvgre_m;
    9999                 :            :         const struct rte_flow_item_nvgre *nvgre_v;
   10000                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10001                 :            :         const char *tni_flow_id_m;
   10002                 :            :         const char *tni_flow_id_v;
   10003                 :            :         char *gre_key_v;
   10004                 :            :         int size;
   10005                 :            :         int i;
   10006                 :            : 
   10007                 :            :         /* For NVGRE, GRE header fields must be set with defined values. */
   10008                 :          0 :         const struct rte_flow_item_gre gre_spec = {
   10009                 :            :                 .c_rsvd0_ver = RTE_BE16(0x2000),
   10010                 :            :                 .protocol = RTE_BE16(RTE_ETHER_TYPE_TEB)
   10011                 :            :         };
   10012                 :          0 :         const struct rte_flow_item_gre gre_mask = {
   10013                 :            :                 .c_rsvd0_ver = RTE_BE16(0xB000),
   10014                 :            :                 .protocol = RTE_BE16(UINT16_MAX),
   10015                 :            :         };
   10016                 :          0 :         const struct rte_flow_item gre_item = {
   10017                 :            :                 .spec = &gre_spec,
   10018                 :            :                 .mask = &gre_mask,
   10019                 :            :                 .last = NULL,
   10020                 :            :         };
   10021                 :          0 :         flow_dv_translate_item_gre(key, &gre_item, pattern_flags, key_type);
   10022   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10023                 :          0 :                 return;
   10024   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, nvgre_v, nvgre_m,
             #  #  #  # ]
   10025                 :            :                     &rte_flow_item_nvgre_mask);
   10026                 :          0 :         tni_flow_id_m = (const char *)nvgre_m->tni;
   10027                 :          0 :         tni_flow_id_v = (const char *)nvgre_v->tni;
   10028                 :            :         size = sizeof(nvgre_m->tni) + sizeof(nvgre_m->flow_id);
   10029                 :          0 :         gre_key_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, gre_key_h);
   10030         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   10031                 :          0 :                 gre_key_v[i] = tni_flow_id_m[i] & tni_flow_id_v[i];
   10032                 :            : }
   10033                 :            : 
   10034                 :            : /**
   10035                 :            :  * Add VXLAN item to the value.
   10036                 :            :  *
   10037                 :            :  * @param[in] dev
   10038                 :            :  *   Pointer to the Ethernet device structure.
   10039                 :            :  * @param[in] attr
   10040                 :            :  *   Flow rule attributes.
   10041                 :            :  * @param[in, out] key
   10042                 :            :  *   Flow matcher value.
   10043                 :            :  * @param[in] item
   10044                 :            :  *   Flow pattern to translate.
   10045                 :            :  * @param[in] inner
   10046                 :            :  *   Item is inner pattern.
   10047                 :            :  * @param[in] wks
   10048                 :            :  *   Matcher workspace.
   10049                 :            :  * @param[in] key_type
   10050                 :            :  *   Set flow matcher mask or value.
   10051                 :            :  */
   10052                 :            : static void
   10053                 :          0 : flow_dv_translate_item_vxlan(struct rte_eth_dev *dev,
   10054                 :            :                              const struct rte_flow_attr *attr,
   10055                 :            :                              void *key, const struct rte_flow_item *item,
   10056                 :            :                              int inner, struct mlx5_dv_matcher_workspace *wks,
   10057                 :            :                              uint32_t key_type)
   10058                 :            : {
   10059                 :            :         const struct rte_flow_item_vxlan *vxlan_m;
   10060                 :            :         const struct rte_flow_item_vxlan *vxlan_v;
   10061                 :            :         void *headers_v;
   10062                 :            :         void *misc_v;
   10063                 :            :         void *misc5_v;
   10064                 :            :         uint32_t tunnel_v;
   10065                 :            :         char *vni_v;
   10066                 :            :         uint16_t dport;
   10067                 :            :         int size;
   10068                 :            :         int i;
   10069                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10070                 :          0 :         const struct rte_flow_item_vxlan nic_mask = {
   10071                 :            :                 .hdr.vni =  { 0xff, 0xff, 0xff },
   10072                 :            :                 .hdr.rsvd1 = 0xff,
   10073                 :            :         };
   10074                 :            : 
   10075                 :            :         misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
   10076         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   10077                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10078         [ #  # ]:          0 :         dport = item->type == RTE_FLOW_ITEM_TYPE_VXLAN ?
   10079                 :            :                 MLX5_UDP_PORT_VXLAN : MLX5_UDP_PORT_VXLAN_GPE;
   10080   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10081         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10082         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10083                 :            :                                  udp_dport, 0xFFFF);
   10084                 :            :                 else
   10085         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10086                 :            :                                  udp_dport, dport);
   10087                 :            :         }
   10088                 :            :         /*
   10089                 :            :          * Read the UDP dport to check if the value satisfies the VXLAN
   10090                 :            :          * matching with MISC5 for CX5.
   10091                 :            :          */
   10092         [ #  # ]:          0 :         if (wks->udp_dport)
   10093                 :            :                 dport = wks->udp_dport;
   10094   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10095                 :          0 :                 return;
   10096   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, vxlan_v, vxlan_m, &nic_mask);
             #  #  #  # ]
   10097                 :            :         if ((item->mask == &nic_mask) &&
   10098                 :            :             ((!attr->group && !(attr->transfer && priv->fdb_def_rule) &&
   10099                 :            :             !priv->sh->tunnel_header_0_1) ||
   10100                 :            :             ((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
   10101                 :            :             !priv->sh->misc5_cap)))
   10102                 :            :                 vxlan_m = &rte_flow_item_vxlan_mask;
   10103         [ #  # ]:          0 :         if ((priv->sh->steering_format_version ==
   10104         [ #  # ]:          0 :              MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 &&
   10105                 :          0 :              dport != MLX5_UDP_PORT_VXLAN) ||
   10106   [ #  #  #  #  :          0 :             (!attr->group && !(attr->transfer && priv->fdb_def_rule)) ||
             #  #  #  # ]
   10107   [ #  #  #  # ]:          0 :             ((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
   10108         [ #  # ]:          0 :             !priv->sh->misc5_cap)) {
   10109                 :            :                 misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10110                 :            :                 size = sizeof(vxlan_m->hdr.vni);
   10111                 :          0 :                 vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, vxlan_vni);
   10112         [ #  # ]:          0 :                 for (i = 0; i < size; ++i)
   10113                 :          0 :                         vni_v[i] = vxlan_m->hdr.vni[i] & vxlan_v->hdr.vni[i];
   10114                 :            :                 return;
   10115                 :            :         }
   10116                 :          0 :         tunnel_v = (vxlan_v->hdr.vni[0] & vxlan_m->hdr.vni[0]) |
   10117                 :          0 :                    (vxlan_v->hdr.vni[1] & vxlan_m->hdr.vni[1]) << 8 |
   10118                 :          0 :                    (vxlan_v->hdr.vni[2] & vxlan_m->hdr.vni[2]) << 16;
   10119                 :          0 :         tunnel_v |= (vxlan_v->hdr.rsvd1 & vxlan_m->hdr.rsvd1) << 24;
   10120         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1, RTE_BE32(tunnel_v));
   10121                 :            : }
   10122                 :            : 
   10123                 :            : /**
   10124                 :            :  * Add VXLAN-GPE item to the value.
   10125                 :            :  *
   10126                 :            :  * @param[in, out] key
   10127                 :            :  *   Flow matcher value.
   10128                 :            :  * @param[in] item
   10129                 :            :  *   Flow pattern to translate.
   10130                 :            :  * @param[in] pattern_flags
   10131                 :            :  *   Item pattern flags.
   10132                 :            :  * @param[in] key_type
   10133                 :            :  *   Set flow matcher mask or value.
   10134                 :            :  */
   10135                 :            : 
   10136                 :            : static void
   10137                 :          0 : flow_dv_translate_item_vxlan_gpe(void *key, const struct rte_flow_item *item,
   10138                 :            :                                  const uint64_t pattern_flags,
   10139                 :            :                                  uint32_t key_type)
   10140                 :            : {
   10141                 :            :         static const struct rte_flow_item_vxlan_gpe dummy_vxlan_gpe_hdr = {{{0}}};
   10142                 :          0 :         const struct rte_flow_item_vxlan_gpe *vxlan_m = item->mask;
   10143                 :          0 :         const struct rte_flow_item_vxlan_gpe *vxlan_v = item->spec;
   10144                 :            :         /* The item was validated to be on the outer side */
   10145                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10146                 :            :         void *misc_v =
   10147                 :            :                 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10148                 :          0 :         char *vni_v =
   10149                 :            :                 MLX5_ADDR_OF(fte_match_set_misc3, misc_v, outer_vxlan_gpe_vni);
   10150                 :            :         int i, size = sizeof(vxlan_m->hdr.vni);
   10151                 :            :         uint8_t flags_m = 0xff;
   10152                 :            :         uint8_t flags_v = 0xc;
   10153                 :            :         uint8_t m_protocol, v_protocol;
   10154                 :            : 
   10155   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10156         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10157         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10158                 :            :                                  0xFFFF);
   10159                 :            :                 else
   10160         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10161                 :            :                                  MLX5_UDP_PORT_VXLAN_GPE);
   10162                 :            :         }
   10163         [ #  # ]:          0 :         if (!vxlan_v) {
   10164                 :            :                 vxlan_v = &dummy_vxlan_gpe_hdr;
   10165                 :            :                 vxlan_m = &dummy_vxlan_gpe_hdr;
   10166                 :            :         } else {
   10167         [ #  # ]:          0 :                 if (!vxlan_m)
   10168                 :            :                         vxlan_m = &rte_flow_item_vxlan_gpe_mask;
   10169                 :            :         }
   10170         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10171                 :            :                 vxlan_v = vxlan_m;
   10172         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
   10173                 :            :                 vxlan_m = vxlan_v;
   10174         [ #  # ]:          0 :         if (vxlan_m->hdr.flags) {
   10175                 :            :                 flags_m = vxlan_m->hdr.flags;
   10176                 :          0 :                 flags_v = vxlan_v->hdr.flags;
   10177                 :            :         }
   10178                 :          0 :         m_protocol = vxlan_m->hdr.protocol;
   10179                 :          0 :         v_protocol = vxlan_v->hdr.protocol;
   10180         [ #  # ]:          0 :         if (!m_protocol) {
   10181                 :            :                 /* Force next protocol to ensure next headers parsing. */
   10182         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_NSH)
   10183                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_NSH;
   10184         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L2)
   10185                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_ETH;
   10186         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV4)
   10187                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_IPV4;
   10188         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV6)
   10189                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_IPV6;
   10190         [ #  # ]:          0 :                 if (v_protocol)
   10191                 :            :                         m_protocol = 0xFF;
   10192                 :            :                 /* Restore the value to mask in mask case. */
   10193         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10194                 :            :                         v_protocol = m_protocol;
   10195                 :            :         }
   10196                 :            :         /*
   10197                 :            :          * If only match flags/protocol/vni field, keep using misc3 for matching.
   10198                 :            :          * If need to match rsvd0 or rsvd1, using misc5 and do not need using misc3.
   10199                 :            :          */
   10200   [ #  #  #  #  :          0 :         if (!(vxlan_m->hdr.rsvd0[0] || vxlan_m->hdr.rsvd0[1] || vxlan_m->hdr.rsvd1)) {
                   #  # ]
   10201         [ #  # ]:          0 :                 for (i = 0; i < size; ++i)
   10202                 :          0 :                         vni_v[i] = vxlan_m->hdr.vni[i] & vxlan_v->hdr.vni[i];
   10203         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc_v, outer_vxlan_gpe_flags,
   10204                 :            :                          flags_m & flags_v);
   10205         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc_v,
   10206                 :            :                          outer_vxlan_gpe_next_protocol, m_protocol & v_protocol);
   10207                 :            :         } else {
   10208                 :            :                 uint32_t tunnel_v;
   10209                 :            :                 void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
   10210                 :            : 
   10211                 :          0 :                 tunnel_v = (flags_m & flags_v) << 24 |
   10212                 :          0 :                            (vxlan_v->hdr.rsvd0[0] & vxlan_m->hdr.rsvd0[0]) << 16 |
   10213                 :          0 :                            (vxlan_v->hdr.rsvd0[1] & vxlan_m->hdr.rsvd0[1]) << 8 |
   10214                 :          0 :                            (m_protocol & v_protocol);
   10215         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0, tunnel_v);
   10216                 :          0 :                 tunnel_v = (vxlan_v->hdr.vni[0] & vxlan_m->hdr.vni[0]) << 24 |
   10217                 :          0 :                            (vxlan_v->hdr.vni[1] & vxlan_m->hdr.vni[1]) << 16 |
   10218                 :          0 :                            (vxlan_v->hdr.vni[2] & vxlan_m->hdr.vni[2]) << 8 |
   10219                 :          0 :                            (vxlan_v->hdr.rsvd1 & vxlan_m->hdr.rsvd1);
   10220         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1, tunnel_v);
   10221                 :            :         }
   10222                 :          0 : }
   10223                 :            : 
   10224                 :            : /**
   10225                 :            :  * Add Geneve item to the value.
   10226                 :            :  *
   10227                 :            :  * @param[in, out] key
   10228                 :            :  *   Flow matcher value.
   10229                 :            :  * @param[in] item
   10230                 :            :  *   Flow pattern to translate.
   10231                 :            :  * @param[in] pattern_flags
   10232                 :            :  *   Item pattern flags.
   10233                 :            :  * @param[in] key_type
   10234                 :            :  *   Set flow matcher mask or value.
   10235                 :            :  */
   10236                 :            : 
   10237                 :            : static void
   10238                 :          0 : flow_dv_translate_item_geneve(void *key, const struct rte_flow_item *item,
   10239                 :            :                               uint64_t pattern_flags, uint32_t key_type)
   10240                 :            : {
   10241                 :            :         static const struct rte_flow_item_geneve empty_geneve = {0,};
   10242                 :          0 :         const struct rte_flow_item_geneve *geneve_m = item->mask;
   10243                 :          0 :         const struct rte_flow_item_geneve *geneve_v = item->spec;
   10244                 :            :         /* GENEVE flow item validation allows single tunnel item */
   10245                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10246                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10247                 :            :         uint16_t gbhdr_m;
   10248                 :            :         uint16_t gbhdr_v;
   10249                 :          0 :         char *vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, geneve_vni);
   10250                 :            :         size_t size = sizeof(geneve_m->vni), i;
   10251                 :            :         uint16_t protocol_m, protocol_v;
   10252                 :            : 
   10253   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10254         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10255         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10256                 :            :                                  0xFFFF);
   10257                 :            :                 else
   10258         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10259                 :            :                                  MLX5_UDP_PORT_GENEVE);
   10260                 :            :         }
   10261         [ #  # ]:          0 :         if (!geneve_v) {
   10262                 :            :                 geneve_v = &empty_geneve;
   10263                 :            :                 geneve_m = &empty_geneve;
   10264                 :            :         } else {
   10265         [ #  # ]:          0 :                 if (!geneve_m)
   10266                 :            :                         geneve_m = &rte_flow_item_geneve_mask;
   10267                 :            :         }
   10268         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10269                 :            :                 geneve_v = geneve_m;
   10270         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
   10271                 :            :                 geneve_m = geneve_v;
   10272         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   10273                 :          0 :                 vni_v[i] = geneve_m->vni[i] & geneve_v->vni[i];
   10274         [ #  # ]:          0 :         gbhdr_m = rte_be_to_cpu_16(geneve_m->ver_opt_len_o_c_rsvd0);
   10275         [ #  # ]:          0 :         gbhdr_v = rte_be_to_cpu_16(geneve_v->ver_opt_len_o_c_rsvd0);
   10276         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_oam,
   10277                 :            :                  MLX5_GENEVE_OAMF_VAL(gbhdr_v) & MLX5_GENEVE_OAMF_VAL(gbhdr_m));
   10278         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len,
   10279                 :            :                  MLX5_GENEVE_OPTLEN_VAL(gbhdr_v) &
   10280                 :            :                  MLX5_GENEVE_OPTLEN_VAL(gbhdr_m));
   10281         [ #  # ]:          0 :         protocol_m = rte_be_to_cpu_16(geneve_m->protocol);
   10282         [ #  # ]:          0 :         protocol_v = rte_be_to_cpu_16(geneve_v->protocol);
   10283         [ #  # ]:          0 :         if (!protocol_m) {
   10284                 :            :                 /* Force next protocol to prevent matchers duplication */
   10285                 :            :                 protocol_v = mlx5_translate_tunnel_etypes(pattern_flags);
   10286                 :            :                 if (protocol_v)
   10287                 :            :                         protocol_m = 0xFFFF;
   10288                 :            :                 /* Restore the value to mask in mask case. */
   10289         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10290                 :            :                         protocol_v = protocol_m;
   10291                 :            :         }
   10292         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_protocol_type,
   10293                 :            :                  protocol_m & protocol_v);
   10294                 :          0 : }
   10295                 :            : 
   10296                 :            : /**
   10297                 :            :  * Create Geneve TLV option resource.
   10298                 :            :  *
   10299                 :            :  * @param[in, out] dev
   10300                 :            :  *   Pointer to rte_eth_dev structure.
   10301                 :            :  * @param[in] item
   10302                 :            :  *   Flow pattern to translate.
   10303                 :            :  * @param[out] error
   10304                 :            :  *   pointer to error structure.
   10305                 :            :  *
   10306                 :            :  * @return
   10307                 :            :  *   0 on success otherwise -errno and errno is set.
   10308                 :            :  */
   10309                 :            : static int
   10310                 :          0 : flow_dev_geneve_tlv_option_resource_register(struct rte_eth_dev *dev,
   10311                 :            :                                              const struct rte_flow_item *item,
   10312                 :            :                                              struct rte_flow_error *error)
   10313                 :            : {
   10314                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10315                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   10316                 :          0 :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource =
   10317                 :            :                         sh->geneve_tlv_option_resource;
   10318                 :            :         struct mlx5_devx_obj *obj;
   10319                 :          0 :         const struct rte_flow_item_geneve_opt *geneve_opt_v = item->spec;
   10320                 :            :         int ret = 0;
   10321                 :            : 
   10322                 :            :         MLX5_ASSERT(sh->config.dv_flow_en == 1);
   10323         [ #  # ]:          0 :         if (!geneve_opt_v)
   10324                 :            :                 return -1;
   10325                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
   10326         [ #  # ]:          0 :         if (geneve_opt_resource != NULL) {
   10327                 :          0 :                 if (geneve_opt_resource->option_class ==
   10328                 :            :                         geneve_opt_v->option_class &&
   10329                 :            :                         geneve_opt_resource->option_type ==
   10330         [ #  # ]:          0 :                         geneve_opt_v->option_type &&
   10331                 :            :                         geneve_opt_resource->length ==
   10332                 :            :                         geneve_opt_v->option_len) {
   10333                 :          0 :                         rte_atomic_fetch_add_explicit(&geneve_opt_resource->refcnt, 1,
   10334                 :            :                                            rte_memory_order_relaxed);
   10335                 :            :                 } else {
   10336                 :          0 :                         ret = rte_flow_error_set(error, ENOMEM,
   10337                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10338                 :            :                                 "Only one GENEVE TLV option supported");
   10339                 :          0 :                         goto exit;
   10340                 :            :                 }
   10341                 :            :         } else {
   10342                 :          0 :                 struct mlx5_devx_geneve_tlv_option_attr attr = {
   10343                 :          0 :                         .option_class = geneve_opt_v->option_class,
   10344                 :          0 :                         .option_type = geneve_opt_v->option_type,
   10345                 :          0 :                         .option_data_len = geneve_opt_v->option_len,
   10346                 :            :                 };
   10347                 :            : 
   10348                 :            :                 /* Create a GENEVE TLV object and resource. */
   10349                 :          0 :                 obj = mlx5_devx_cmd_create_geneve_tlv_option(sh->cdev->ctx,
   10350                 :            :                                                              &attr);
   10351         [ #  # ]:          0 :                 if (!obj) {
   10352                 :          0 :                         ret = rte_flow_error_set(error, ENODATA,
   10353                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10354                 :            :                                 "Failed to create GENEVE TLV Devx object");
   10355                 :          0 :                         goto exit;
   10356                 :            :                 }
   10357                 :          0 :                 sh->geneve_tlv_option_resource =
   10358                 :          0 :                                 mlx5_malloc(MLX5_MEM_ZERO,
   10359                 :            :                                                 sizeof(*geneve_opt_resource),
   10360                 :            :                                                 0, SOCKET_ID_ANY);
   10361         [ #  # ]:          0 :                 if (!sh->geneve_tlv_option_resource) {
   10362                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy(obj));
   10363                 :          0 :                         ret = rte_flow_error_set(error, ENOMEM,
   10364                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10365                 :            :                                 "GENEVE TLV object memory allocation failed");
   10366                 :          0 :                         goto exit;
   10367                 :            :                 }
   10368                 :            :                 geneve_opt_resource = sh->geneve_tlv_option_resource;
   10369                 :          0 :                 geneve_opt_resource->obj = obj;
   10370                 :          0 :                 geneve_opt_resource->option_class = geneve_opt_v->option_class;
   10371                 :          0 :                 geneve_opt_resource->option_type = geneve_opt_v->option_type;
   10372                 :          0 :                 geneve_opt_resource->length = geneve_opt_v->option_len;
   10373                 :          0 :                 rte_atomic_store_explicit(&geneve_opt_resource->refcnt, 1,
   10374                 :            :                                 rte_memory_order_relaxed);
   10375                 :            :         }
   10376                 :          0 : exit:
   10377                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
   10378                 :          0 :         return ret;
   10379                 :            : }
   10380                 :            : 
   10381                 :            : /**
   10382                 :            :  * Add Geneve TLV option item to value.
   10383                 :            :  *
   10384                 :            :  * @param[in, out] dev
   10385                 :            :  *   Pointer to rte_eth_dev structure.
   10386                 :            :  * @param[in, out] key
   10387                 :            :  *   Flow matcher value.
   10388                 :            :  * @param[in] item
   10389                 :            :  *   Flow pattern to translate.
   10390                 :            :  * @param[in] key_type
   10391                 :            :  *   Set flow matcher mask or value.
   10392                 :            :  * @param[out] error
   10393                 :            :  *   Pointer to error structure.
   10394                 :            :  */
   10395                 :            : static int
   10396                 :          0 : flow_dv_translate_item_geneve_opt(struct rte_eth_dev *dev, void *key,
   10397                 :            :                                   const struct rte_flow_item *item,
   10398                 :            :                                   uint32_t key_type,
   10399                 :            :                                   struct rte_flow_error *error)
   10400                 :            : {
   10401                 :            :         const struct rte_flow_item_geneve_opt *geneve_opt_m;
   10402                 :            :         const struct rte_flow_item_geneve_opt *geneve_opt_v;
   10403                 :          0 :         const struct rte_flow_item_geneve_opt *orig_spec = item->spec;
   10404                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10405                 :          0 :         rte_be32_t opt_data_key = 0, opt_data_mask = 0;
   10406                 :            :         size_t option_byte_len;
   10407                 :            :         int ret = 0;
   10408                 :            : 
   10409   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type) || !orig_spec)
          #  #  #  #  #  
                #  #  # ]
   10410                 :            :                 return -1;
   10411   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, geneve_opt_v, geneve_opt_m,
             #  #  #  # ]
   10412                 :            :                          &rte_flow_item_geneve_opt_mask);
   10413                 :            :         /*
   10414                 :            :          * Register resource requires item spec for SW steering,
   10415                 :            :          * for HW steering resources is registered explicitly by user.
   10416                 :            :          */
   10417         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW_V) {
   10418                 :          0 :                 ret = flow_dev_geneve_tlv_option_resource_register(dev, item,
   10419                 :            :                                                                    error);
   10420         [ #  # ]:          0 :                 if (ret) {
   10421                 :          0 :                         DRV_LOG(ERR, "Failed to create geneve_tlv_obj");
   10422                 :          0 :                         return ret;
   10423                 :            :                 }
   10424                 :            :         }
   10425                 :            :         /* Convert the option length from DW to bytes for using memcpy. */
   10426                 :          0 :         option_byte_len = RTE_MIN((size_t)(orig_spec->option_len * 4),
   10427                 :            :                                   sizeof(rte_be32_t));
   10428         [ #  # ]:          0 :         if (geneve_opt_v->data) {
   10429                 :            :                 memcpy(&opt_data_key, geneve_opt_v->data, option_byte_len);
   10430                 :          0 :                 memcpy(&opt_data_mask, geneve_opt_m->data, option_byte_len);
   10431   [ #  #  #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v,
   10432                 :            :                          geneve_tlv_option_0_data,
   10433                 :            :                          rte_be_to_cpu_32(opt_data_key & opt_data_mask));
   10434                 :            :         }
   10435                 :            :         return ret;
   10436                 :            : }
   10437                 :            : 
   10438                 :            : /**
   10439                 :            :  * Add MPLS item to the value.
   10440                 :            :  *
   10441                 :            :  * @param[in, out] key
   10442                 :            :  *   Flow matcher value.
   10443                 :            :  * @param[in] item
   10444                 :            :  *   Flow pattern to translate.
   10445                 :            :  * @param[in] prev_layer
   10446                 :            :  *   The protocol layer indicated in previous item.
   10447                 :            :  * @param[in] inner
   10448                 :            :  *   Item is inner pattern.
   10449                 :            :  * @param[in] key_type
   10450                 :            :  *   Set flow matcher mask or value.
   10451                 :            :  */
   10452                 :            : static void
   10453                 :          0 : flow_dv_translate_item_mpls(void *key, const struct rte_flow_item *item,
   10454                 :            :                             uint64_t prev_layer, int inner,
   10455                 :            :                             uint32_t key_type)
   10456                 :            : {
   10457                 :            :         const uint32_t *in_mpls_m;
   10458                 :            :         const uint32_t *in_mpls_v;
   10459                 :            :         uint32_t *out_mpls_v = 0;
   10460                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10461                 :          0 :         void *misc2_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
   10462                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10463                 :            : 
   10464      [ #  #  # ]:          0 :         switch (prev_layer) {
   10465                 :          0 :         case MLX5_FLOW_LAYER_OUTER_L4_UDP:
   10466   [ #  #  #  # ]:          0 :                 if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10467         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10468         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10469                 :            :                                          udp_dport, 0xffff);
   10470                 :            :                         else
   10471         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10472                 :            :                                          udp_dport, MLX5_UDP_PORT_MPLS);
   10473                 :            :                 }
   10474                 :            :                 break;
   10475                 :          0 :         case MLX5_FLOW_LAYER_GRE:
   10476                 :            :                 /* Fall-through. */
   10477                 :            :         case MLX5_FLOW_LAYER_GRE_KEY:
   10478   [ #  #  #  # ]:          0 :                 if (!MLX5_GET16(fte_match_set_misc, misc_v, gre_protocol)) {
   10479         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10480         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_misc, misc_v,
   10481                 :            :                                          gre_protocol, 0xffff);
   10482                 :            :                         else
   10483         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_misc, misc_v,
   10484                 :            :                                          gre_protocol, RTE_ETHER_TYPE_MPLS);
   10485                 :            :                 }
   10486                 :            :                 break;
   10487                 :            :         default:
   10488                 :            :                 break;
   10489                 :            :         }
   10490   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10491                 :            :                 return;
   10492   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, in_mpls_v, in_mpls_m,
             #  #  #  # ]
   10493                 :            :                          &rte_flow_item_mpls_mask);
   10494      [ #  #  # ]:          0 :         switch (prev_layer) {
   10495                 :          0 :         case MLX5_FLOW_LAYER_OUTER_L4_UDP:
   10496                 :          0 :                 out_mpls_v =
   10497                 :            :                         (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
   10498                 :            :                                                  outer_first_mpls_over_udp);
   10499                 :          0 :                 break;
   10500                 :          0 :         case MLX5_FLOW_LAYER_GRE:
   10501                 :          0 :                 out_mpls_v =
   10502                 :            :                         (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
   10503                 :            :                                                  outer_first_mpls_over_gre);
   10504                 :          0 :                 break;
   10505                 :          0 :         default:
   10506                 :            :                 /* Inner MPLS not over GRE is not supported. */
   10507         [ #  # ]:          0 :                 if (!inner)
   10508                 :            :                         out_mpls_v =
   10509                 :            :                                 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2,
   10510                 :            :                                                          misc2_v,
   10511                 :            :                                                          outer_first_mpls);
   10512                 :            :                 break;
   10513                 :            :         }
   10514                 :            :         if (out_mpls_v)
   10515                 :          0 :                 *out_mpls_v = *in_mpls_v & *in_mpls_m;
   10516                 :            : }
   10517                 :            : 
   10518                 :            : /**
   10519                 :            :  * Add metadata register item to matcher
   10520                 :            :  *
   10521                 :            :  * @param[in, out] key
   10522                 :            :  *   Flow matcher value.
   10523                 :            :  * @param[in] reg_type
   10524                 :            :  *   Type of device metadata register
   10525                 :            :  * @param[in] data
   10526                 :            :  *   Register data
   10527                 :            :  * @param[in] mask
   10528                 :            :  *   Register mask
   10529                 :            :  */
   10530                 :            : static void
   10531                 :          0 : flow_dv_match_meta_reg(void *key, enum modify_reg reg_type,
   10532                 :            :                        uint32_t data, uint32_t mask)
   10533                 :            : {
   10534                 :            :         void *misc2_v =
   10535                 :            :                 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
   10536                 :            :         uint32_t temp;
   10537                 :            : 
   10538         [ #  # ]:          0 :         if (!key)
   10539                 :            :                 return;
   10540                 :          0 :         data &= mask;
   10541   [ #  #  #  #  :          0 :         switch (reg_type) {
          #  #  #  #  #  
                   #  # ]
   10542                 :          0 :         case REG_A:
   10543         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_a, data);
   10544                 :          0 :                 break;
   10545                 :          0 :         case REG_B:
   10546         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_b, data);
   10547                 :          0 :                 break;
   10548                 :          0 :         case REG_C_0:
   10549                 :            :                 /*
   10550                 :            :                  * The metadata register C0 field might be divided into
   10551                 :            :                  * source vport index and META item value, we should set
   10552                 :            :                  * this field according to specified mask, not as whole one.
   10553                 :            :                  */
   10554         [ #  # ]:          0 :                 temp = MLX5_GET(fte_match_set_misc2, misc2_v, metadata_reg_c_0);
   10555         [ #  # ]:          0 :                 if (mask)
   10556                 :          0 :                         temp &= ~mask;
   10557                 :          0 :                 temp |= data;
   10558         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, temp);
   10559                 :          0 :                 break;
   10560                 :          0 :         case REG_C_1:
   10561         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_1, data);
   10562                 :          0 :                 break;
   10563                 :          0 :         case REG_C_2:
   10564         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_2, data);
   10565                 :          0 :                 break;
   10566                 :          0 :         case REG_C_3:
   10567         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_3, data);
   10568                 :          0 :                 break;
   10569                 :          0 :         case REG_C_4:
   10570         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_4, data);
   10571                 :          0 :                 break;
   10572                 :          0 :         case REG_C_5:
   10573         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_5, data);
   10574                 :          0 :                 break;
   10575                 :          0 :         case REG_C_6:
   10576         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_6, data);
   10577                 :          0 :                 break;
   10578                 :          0 :         case REG_C_7:
   10579         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_7, data);
   10580                 :          0 :                 break;
   10581                 :            :         default:
   10582                 :            :                 MLX5_ASSERT(false);
   10583                 :            :                 break;
   10584                 :            :         }
   10585                 :            : }
   10586                 :            : 
   10587                 :            : /**
   10588                 :            :  * Add metadata register item to matcher
   10589                 :            :  *
   10590                 :            :  * @param[in, out] matcher
   10591                 :            :  *   Flow matcher.
   10592                 :            :  * @param[in, out] key
   10593                 :            :  *   Flow matcher value.
   10594                 :            :  * @param[in] reg_type
   10595                 :            :  *   Type of device metadata register
   10596                 :            :  * @param[in] value
   10597                 :            :  *   Register value
   10598                 :            :  * @param[in] mask
   10599                 :            :  *   Register mask
   10600                 :            :  */
   10601                 :            : static void
   10602                 :            : flow_dv_match_meta_reg_all(void *matcher, void *key, enum modify_reg reg_type,
   10603                 :            :                            uint32_t data, uint32_t mask)
   10604                 :            : {
   10605                 :          0 :         flow_dv_match_meta_reg(key, reg_type, data, mask);
   10606                 :          0 :         flow_dv_match_meta_reg(matcher, reg_type, mask, mask);
   10607                 :            : }
   10608                 :            : 
   10609                 :            : /**
   10610                 :            :  * Add MARK item to matcher
   10611                 :            :  *
   10612                 :            :  * @param[in] dev
   10613                 :            :  *   The device to configure through.
   10614                 :            :  * @param[in, out] key
   10615                 :            :  *   Flow matcher value.
   10616                 :            :  * @param[in] item
   10617                 :            :  *   Flow pattern to translate.
   10618                 :            :  * @param[in] key_type
   10619                 :            :  *   Set flow matcher mask or value.
   10620                 :            :  */
   10621                 :            : static void
   10622                 :          0 : flow_dv_translate_item_mark(struct rte_eth_dev *dev, void *key,
   10623                 :            :                             const struct rte_flow_item *item,
   10624                 :            :                             uint32_t key_type)
   10625                 :            : {
   10626                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10627                 :            :         const struct rte_flow_item_mark *mark;
   10628                 :            :         uint32_t value;
   10629                 :            :         uint32_t mask = 0;
   10630                 :            : 
   10631         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW) {
   10632         [ #  # ]:          0 :                 mark = item->mask ? (const void *)item->mask :
   10633                 :            :                                     &rte_flow_item_mark_mask;
   10634                 :          0 :                 mask = mark->id;
   10635         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M) {
   10636                 :            :                         value = mask;
   10637                 :            :                 } else {
   10638                 :          0 :                         mark = (const void *)item->spec;
   10639                 :            :                         MLX5_ASSERT(mark);
   10640                 :          0 :                         value = mark->id;
   10641                 :            :                 }
   10642                 :            :         } else {
   10643         [ #  # ]:          0 :                 mark = (key_type == MLX5_SET_MATCHER_HS_V) ?
   10644                 :            :                         (const void *)item->spec : (const void *)item->mask;
   10645                 :            :                 MLX5_ASSERT(mark);
   10646                 :          0 :                 value = mark->id;
   10647         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_HS_M)
   10648                 :            :                         mask = value;
   10649                 :            :         }
   10650                 :          0 :         mask &= priv->sh->dv_mark_mask;
   10651                 :          0 :         value &= mask;
   10652         [ #  # ]:          0 :         if (mask) {
   10653                 :            :                 enum modify_reg reg;
   10654                 :            : 
   10655                 :            :                 /* Get the metadata register index for the mark. */
   10656                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, NULL);
   10657                 :            :                 MLX5_ASSERT(reg > 0);
   10658         [ #  # ]:          0 :                 if (reg == REG_C_0) {
   10659                 :          0 :                         struct mlx5_priv *priv = dev->data->dev_private;
   10660                 :          0 :                         uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10661                 :            :                         uint32_t shl_c0 = rte_bsf32(msk_c0);
   10662                 :            : 
   10663                 :          0 :                         mask &= msk_c0;
   10664                 :          0 :                         mask <<= shl_c0;
   10665                 :          0 :                         value <<= shl_c0;
   10666                 :            :                 }
   10667                 :          0 :                 flow_dv_match_meta_reg(key, reg, value, mask);
   10668                 :            :         }
   10669                 :          0 : }
   10670                 :            : 
   10671                 :            : /**
   10672                 :            :  * Add META item to matcher
   10673                 :            :  *
   10674                 :            :  * @param[in] dev
   10675                 :            :  *   The devich to configure through.
   10676                 :            :  * @param[in, out] key
   10677                 :            :  *   Flow matcher value.
   10678                 :            :  * @param[in] attr
   10679                 :            :  *   Attributes of flow that includes this item.
   10680                 :            :  * @param[in] item
   10681                 :            :  *   Flow pattern to translate.
   10682                 :            :  * @param[in] key_type
   10683                 :            :  *   Set flow matcher mask or value.
   10684                 :            :  */
   10685                 :            : static void
   10686                 :          0 : flow_dv_translate_item_meta(struct rte_eth_dev *dev,
   10687                 :            :                             void *key,
   10688                 :            :                             const struct rte_flow_attr *attr,
   10689                 :            :                             const struct rte_flow_item *item,
   10690                 :            :                             uint32_t key_type)
   10691                 :            : {
   10692                 :            :         const struct rte_flow_item_meta *meta_m;
   10693                 :            :         const struct rte_flow_item_meta *meta_v;
   10694                 :            :         uint32_t value;
   10695                 :            :         uint32_t mask = 0;
   10696                 :            :         int reg;
   10697                 :            : 
   10698   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10699                 :            :                 return;
   10700   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, meta_v, meta_m,
             #  #  #  # ]
   10701                 :            :                          &rte_flow_item_meta_mask);
   10702                 :          0 :         value = meta_v->data;
   10703                 :          0 :         mask = meta_m->data;
   10704         [ #  # ]:          0 :         if (key_type == MLX5_SET_MATCHER_HS_M)
   10705                 :            :                 mask = value;
   10706                 :            :         /*
   10707                 :            :          * In the current implementation, REG_B cannot be used to match.
   10708                 :            :          * Force to use REG_C_1 in HWS root table as other tables.
   10709                 :            :          * This map may change.
   10710                 :            :          * NIC: modify - REG_B to be present in SW
   10711                 :            :          *      match - REG_C_1 when copied from FDB, different from SWS
   10712                 :            :          * FDB: modify - REG_C_1 in Xmeta mode, REG_NON in legacy mode
   10713                 :            :          *      match - REG_C_1 in FDB
   10714                 :            :          */
   10715         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   10716                 :          0 :                 reg = flow_dv_get_metadata_reg(dev, attr, NULL);
   10717                 :            :         else
   10718                 :            :                 reg = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_META, 0);
   10719         [ #  # ]:          0 :         if (reg < 0)
   10720                 :            :                 return;
   10721                 :            :         MLX5_ASSERT(reg != REG_NON);
   10722         [ #  # ]:          0 :         if (reg == REG_C_0) {
   10723                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
   10724                 :          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10725                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
   10726                 :            : 
   10727                 :          0 :                 mask &= msk_c0;
   10728                 :          0 :                 mask <<= shl_c0;
   10729                 :          0 :                 value <<= shl_c0;
   10730                 :            :         }
   10731                 :          0 :         flow_dv_match_meta_reg(key, reg, value, mask);
   10732                 :            : }
   10733                 :            : 
   10734                 :            : /**
   10735                 :            :  * Add vport metadata Reg C0 item to matcher
   10736                 :            :  *
   10737                 :            :  * @param[in, out] key
   10738                 :            :  *   Flow matcher value.
   10739                 :            :  * @param[in] value
   10740                 :            :  *   Register value
   10741                 :            :  * @param[in] mask
   10742                 :            :  *   Register mask
   10743                 :            :  */
   10744                 :            : static void
   10745                 :            : flow_dv_translate_item_meta_vport(void *key, uint32_t value, uint32_t mask)
   10746                 :            : {
   10747                 :          0 :         flow_dv_match_meta_reg(key, REG_C_0, value, mask);
   10748                 :          0 : }
   10749                 :            : 
   10750                 :            : /**
   10751                 :            :  * Add tag item to matcher
   10752                 :            :  *
   10753                 :            :  * @param[in] dev
   10754                 :            :  *   The devich to configure through.
   10755                 :            :  * @param[in, out] key
   10756                 :            :  *   Flow matcher value.
   10757                 :            :  * @param[in] item
   10758                 :            :  *   Flow pattern to translate.
   10759                 :            :  * @param[in] key_type
   10760                 :            :  *   Set flow matcher mask or value.
   10761                 :            :  */
   10762                 :            : static void
   10763                 :          0 : flow_dv_translate_mlx5_item_tag(struct rte_eth_dev *dev, void *key,
   10764                 :            :                                 const struct rte_flow_item *item,
   10765                 :            :                                 uint32_t key_type)
   10766                 :            : {
   10767                 :          0 :         const struct mlx5_rte_flow_item_tag *tag_v = item->spec;
   10768                 :          0 :         const struct mlx5_rte_flow_item_tag *tag_m = item->mask;
   10769                 :            :         uint32_t mask, value;
   10770                 :            : 
   10771                 :            :         MLX5_ASSERT(tag_v);
   10772                 :          0 :         value = tag_v->data;
   10773         [ #  # ]:          0 :         mask = tag_m ? tag_m->data : UINT32_MAX;
   10774         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10775                 :            :                 value = mask;
   10776         [ #  # ]:          0 :         if (tag_v->id == REG_C_0) {
   10777                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
   10778                 :          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10779                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
   10780                 :            : 
   10781                 :          0 :                 mask &= msk_c0;
   10782                 :          0 :                 mask <<= shl_c0;
   10783                 :          0 :                 value <<= shl_c0;
   10784                 :            :         }
   10785                 :          0 :         flow_dv_match_meta_reg(key, tag_v->id, value, mask);
   10786                 :          0 : }
   10787                 :            : 
   10788                 :            : /**
   10789                 :            :  * Add TAG item to matcher
   10790                 :            :  *
   10791                 :            :  * @param[in] dev
   10792                 :            :  *   The devich to configure through.
   10793                 :            :  * @param[in, out] key
   10794                 :            :  *   Flow matcher value.
   10795                 :            :  * @param[in] item
   10796                 :            :  *   Flow pattern to translate.
   10797                 :            :  * @param[in] key_type
   10798                 :            :  *   Set flow matcher mask or value.
   10799                 :            :  */
   10800                 :            : static void
   10801                 :          0 : flow_dv_translate_item_tag(struct rte_eth_dev *dev, void *key,
   10802                 :            :                            const struct rte_flow_item *item,
   10803                 :            :                            uint32_t key_type)
   10804                 :            : {
   10805                 :          0 :         const struct rte_flow_item_tag *tag_vv = item->spec;
   10806                 :            :         const struct rte_flow_item_tag *tag_v;
   10807                 :            :         const struct rte_flow_item_tag *tag_m;
   10808                 :            :         int reg;
   10809                 :            :         uint32_t index;
   10810                 :            : 
   10811   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10812                 :            :                 return;
   10813   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, tag_v, tag_m,
             #  #  #  # ]
   10814                 :            :                 &rte_flow_item_tag_mask);
   10815                 :            :         /* When set mask, the index should be from spec. */
   10816         [ #  # ]:          0 :         index = tag_vv ? tag_vv->index : tag_v->index;
   10817                 :            :         /* Get the metadata register index for the tag. */
   10818         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   10819                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, index, NULL);
   10820                 :            :         else
   10821                 :            :                 reg = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_TAG, index);
   10822                 :            :         MLX5_ASSERT(reg > 0);
   10823                 :          0 :         flow_dv_match_meta_reg(key, (enum modify_reg)reg, tag_v->data, tag_m->data);
   10824                 :            : }
   10825                 :            : 
   10826                 :            : /**
   10827                 :            :  * Add source vport match to the specified matcher.
   10828                 :            :  *
   10829                 :            :  * @param[in, out] key
   10830                 :            :  *   Flow matcher value.
   10831                 :            :  * @param[in] port
   10832                 :            :  *   Source vport value to match
   10833                 :            :  */
   10834                 :            : static void
   10835                 :            : flow_dv_translate_item_source_vport(void *key,
   10836                 :            :                                     int16_t port)
   10837                 :            : {
   10838                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10839                 :            : 
   10840   [ #  #  #  #  :          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_port, port);
                   #  # ]
   10841                 :          0 : }
   10842                 :            : 
   10843                 :            : /**
   10844                 :            :  * Translate port-id item to eswitch match on  port-id.
   10845                 :            :  *
   10846                 :            :  * @param[in] dev
   10847                 :            :  *   The devich to configure through.
   10848                 :            :  * @param[in, out] key
   10849                 :            :  *   Flow matcher value.
   10850                 :            :  * @param[in] item
   10851                 :            :  *   Flow pattern to translate.
   10852                 :            :  * @param[in] attr
   10853                 :            :  *   Flow attributes.
   10854                 :            :  * @param[in] key_type
   10855                 :            :  *   Set flow matcher mask or value.
   10856                 :            :  *
   10857                 :            :  * @return
   10858                 :            :  *   0 on success, a negative errno value otherwise.
   10859                 :            :  */
   10860                 :            : static int
   10861                 :          0 : flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *key,
   10862                 :            :                                const struct rte_flow_item *item,
   10863                 :            :                                const struct rte_flow_attr *attr,
   10864                 :            :                                uint32_t key_type)
   10865                 :            : {
   10866         [ #  # ]:          0 :         const struct rte_flow_item_port_id *pid_m = item ? item->mask : NULL;
   10867         [ #  # ]:          0 :         const struct rte_flow_item_port_id *pid_v = item ? item->spec : NULL;
   10868                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   10869                 :            :         struct mlx5_priv *priv;
   10870                 :            :         uint16_t mask, id;
   10871                 :            :         uint32_t vport_meta;
   10872                 :            : 
   10873                 :            :         MLX5_ASSERT(wks);
   10874   [ #  #  #  # ]:          0 :         if (pid_v && pid_v->id == MLX5_PORT_ESW_MGR) {
   10875                 :          0 :                 flow_dv_translate_item_source_vport(key,
   10876         [ #  # ]:          0 :                                 key_type & MLX5_SET_MATCHER_V ?
   10877                 :          0 :                                 mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10878                 :          0 :                 return 0;
   10879                 :            :         }
   10880         [ #  # ]:          0 :         mask = pid_m ? pid_m->id : 0xffff;
   10881         [ #  # ]:          0 :         id = pid_v ? pid_v->id : dev->data->port_id;
   10882                 :          0 :         priv = mlx5_port_to_eswitch_info(id, item == NULL);
   10883         [ #  # ]:          0 :         if (!priv)
   10884                 :          0 :                 return -rte_errno;
   10885         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   10886                 :            :                 id = mask;
   10887                 :          0 :                 vport_meta = priv->vport_meta_mask;
   10888                 :            :         } else {
   10889                 :          0 :                 id = priv->vport_id;
   10890                 :          0 :                 vport_meta = priv->vport_meta_tag;
   10891                 :          0 :                 wks->vport_meta_tag = vport_meta;
   10892                 :            :         }
   10893                 :            :         /*
   10894                 :            :          * Translate to vport field or to metadata, depending on mode.
   10895                 :            :          * Kernel can use either misc.source_port or half of C0 metadata
   10896                 :            :          * register.
   10897                 :            :          */
   10898         [ #  # ]:          0 :         if (priv->vport_meta_mask) {
   10899                 :            :                 /*
   10900                 :            :                  * Provide the hint for SW steering library
   10901                 :            :                  * to insert the flow into ingress domain and
   10902                 :            :                  * save the extra vport match.
   10903                 :            :                  */
   10904   [ #  #  #  # ]:          0 :                 if (mask == 0xffff && priv->vport_id == 0xffff &&
   10905   [ #  #  #  # ]:          0 :                     priv->pf_bond < 0 && attr->transfer)
   10906         [ #  # ]:          0 :                         flow_dv_translate_item_source_vport(key, id);
   10907                 :            :                 /*
   10908                 :            :                  * We should always set the vport metadata register,
   10909                 :            :                  * otherwise the SW steering library can drop
   10910                 :            :                  * the rule if wire vport metadata value is not zero,
   10911                 :            :                  * it depends on kernel configuration.
   10912                 :            :                  */
   10913                 :          0 :                 flow_dv_translate_item_meta_vport
   10914                 :            :                                 (key, vport_meta, priv->vport_meta_mask);
   10915                 :            :         } else {
   10916         [ #  # ]:          0 :                 flow_dv_translate_item_source_vport(key, id);
   10917                 :            :         }
   10918                 :            :         return 0;
   10919                 :            : }
   10920                 :            : 
   10921                 :            : /**
   10922                 :            :  * Translate port representor item to eswitch match on port id.
   10923                 :            :  *
   10924                 :            :  * @param[in] dev
   10925                 :            :  *   The devich to configure through.
   10926                 :            :  * @param[in, out] key
   10927                 :            :  *   Flow matcher value.
   10928                 :            :  * @param[in] key_type
   10929                 :            :  *   Set flow matcher mask or value.
   10930                 :            :  *
   10931                 :            :  * @return
   10932                 :            :  *   0 on success, a negative errno value otherwise.
   10933                 :            :  */
   10934                 :            : static int
   10935                 :          0 : flow_dv_translate_item_port_representor(struct rte_eth_dev *dev, void *key,
   10936                 :            :                                         uint32_t key_type)
   10937                 :            : {
   10938                 :          0 :         flow_dv_translate_item_source_vport(key,
   10939         [ #  # ]:          0 :                         key_type & MLX5_SET_MATCHER_V ?
   10940                 :          0 :                         mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10941                 :          0 :         return 0;
   10942                 :            : }
   10943                 :            : 
   10944                 :            : /**
   10945                 :            :  * Translate represented port item to eswitch match on port id.
   10946                 :            :  *
   10947                 :            :  * @param[in] dev
   10948                 :            :  *   The devich to configure through.
   10949                 :            :  * @param[in, out] key
   10950                 :            :  *   Flow matcher value.
   10951                 :            :  * @param[in] item
   10952                 :            :  *   Flow pattern to translate.
   10953                 :            :  * @param[in]
   10954                 :            :  *   Flow attributes.
   10955                 :            :  *
   10956                 :            :  * @return
   10957                 :            :  *   0 on success, a negative errno value otherwise.
   10958                 :            :  */
   10959                 :            : static int
   10960                 :          0 : flow_dv_translate_item_represented_port(struct rte_eth_dev *dev, void *key,
   10961                 :            :                                         const struct rte_flow_item *item,
   10962                 :            :                                         const struct rte_flow_attr *attr,
   10963                 :            :                                         uint32_t key_type)
   10964                 :            : {
   10965         [ #  # ]:          0 :         const struct rte_flow_item_ethdev *pid_m = item ? item->mask : NULL;
   10966         [ #  # ]:          0 :         const struct rte_flow_item_ethdev *pid_v = item ? item->spec : NULL;
   10967                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   10968                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10969                 :            :         uint16_t mask, id;
   10970                 :            :         uint32_t vport_meta;
   10971                 :            :         bool vport_match = false;
   10972                 :            : 
   10973                 :            :         MLX5_ASSERT(wks);
   10974                 :            : #ifndef HAVE_IBV_DEVICE_ATTR_ESW_MGR_REG_C0
   10975         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
   10976                 :            :                 vport_match = true;
   10977                 :            : #endif
   10978         [ #  # ]:          0 :         if (!pid_m && !pid_v)
   10979                 :            :                 return 0;
   10980   [ #  #  #  # ]:          0 :         if (pid_v && pid_v->port_id == UINT16_MAX) {
   10981   [ #  #  #  # ]:          0 :                 if (priv->sh->config.dv_flow_en != 2 || vport_match) {
   10982                 :          0 :                         flow_dv_translate_item_source_vport
   10983         [ #  # ]:          0 :                                 (key, key_type & MLX5_SET_MATCHER_V ?
   10984                 :          0 :                                  mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10985                 :            :                 } else {
   10986         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10987                 :          0 :                                 vport_meta = priv->sh->dev_cap.esw_info.regc_mask;
   10988                 :            :                         else
   10989                 :          0 :                                 vport_meta = priv->sh->dev_cap.esw_info.regc_value;
   10990                 :          0 :                         flow_dv_translate_item_meta_vport(key, vport_meta,
   10991                 :            :                                                           priv->sh->dev_cap.esw_info.regc_mask);
   10992                 :            :                 }
   10993                 :          0 :                 return 0;
   10994                 :            :         }
   10995         [ #  # ]:          0 :         mask = pid_m ? pid_m->port_id : UINT16_MAX;
   10996         [ #  # ]:          0 :         id = pid_v ? pid_v->port_id : dev->data->port_id;
   10997                 :          0 :         priv = mlx5_port_to_eswitch_info(id, item == NULL);
   10998         [ #  # ]:          0 :         if (!priv)
   10999                 :          0 :                 return -rte_errno;
   11000         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   11001                 :            :                 id = mask;
   11002                 :          0 :                 vport_meta = priv->vport_meta_mask;
   11003                 :            :         } else {
   11004                 :          0 :                 id = priv->vport_id;
   11005                 :          0 :                 vport_meta = priv->vport_meta_tag;
   11006                 :          0 :                 wks->vport_meta_tag = vport_meta;
   11007                 :            :         }
   11008                 :            :         /*
   11009                 :            :          * Translate to vport field or to metadata, depending on mode.
   11010                 :            :          * Kernel can use either misc.source_port or half of C0 metadata
   11011                 :            :          * register.
   11012                 :            :          */
   11013   [ #  #  #  # ]:          0 :         if (priv->vport_meta_mask && !vport_match) {
   11014                 :            :                 /*
   11015                 :            :                  * Provide the hint for SW steering library
   11016                 :            :                  * to insert the flow into ingress domain and
   11017                 :            :                  * save the extra vport match.
   11018                 :            :                  */
   11019   [ #  #  #  # ]:          0 :                 if (mask == UINT16_MAX && priv->vport_id == UINT16_MAX &&
   11020   [ #  #  #  # ]:          0 :                     priv->pf_bond < 0 && attr->transfer &&
   11021         [ #  # ]:          0 :                     priv->sh->config.dv_flow_en != 2)
   11022         [ #  # ]:          0 :                         flow_dv_translate_item_source_vport(key, id);
   11023                 :            :                 /*
   11024                 :            :                  * We should always set the vport metadata register,
   11025                 :            :                  * otherwise the SW steering library can drop
   11026                 :            :                  * the rule if wire vport metadata value is not zero,
   11027                 :            :                  * it depends on kernel configuration.
   11028                 :            :                  */
   11029                 :          0 :                 flow_dv_translate_item_meta_vport(key, vport_meta,
   11030                 :            :                                                   priv->vport_meta_mask);
   11031                 :            :         } else {
   11032         [ #  # ]:          0 :                 flow_dv_translate_item_source_vport(key, id);
   11033                 :            :         }
   11034                 :            :         return 0;
   11035                 :            : }
   11036                 :            : 
   11037                 :            : /**
   11038                 :            :  * Translate port-id item to eswitch match on  port-id.
   11039                 :            :  *
   11040                 :            :  * @param[in] dev
   11041                 :            :  *   The devich to configure through.
   11042                 :            :  * @param[in, out] matcher
   11043                 :            :  *   Flow matcher.
   11044                 :            :  * @param[in, out] key
   11045                 :            :  *   Flow matcher value.
   11046                 :            :  * @param[in] item
   11047                 :            :  *   Flow pattern to translate.
   11048                 :            :  * @param[in] attr
   11049                 :            :  *   Flow attributes.
   11050                 :            :  *
   11051                 :            :  * @return
   11052                 :            :  *   0 on success, a negative errno value otherwise.
   11053                 :            :  */
   11054                 :            : static int
   11055                 :          0 : flow_dv_translate_item_port_id_all(struct rte_eth_dev *dev,
   11056                 :            :                                void *matcher, void *key,
   11057                 :            :                                const struct rte_flow_item *item,
   11058                 :            :                                const struct rte_flow_attr *attr)
   11059                 :            : {
   11060                 :            :         int ret;
   11061                 :            : 
   11062                 :          0 :         ret = flow_dv_translate_item_port_id
   11063                 :            :                         (dev, matcher, item, attr, MLX5_SET_MATCHER_SW_M);
   11064         [ #  # ]:          0 :         if (ret)
   11065                 :            :                 return ret;
   11066                 :          0 :         ret = flow_dv_translate_item_port_id
   11067                 :            :                         (dev, key, item, attr, MLX5_SET_MATCHER_SW_V);
   11068                 :          0 :         return ret;
   11069                 :            : }
   11070                 :            : 
   11071                 :            : 
   11072                 :            : /**
   11073                 :            :  * Add ICMP6 item to the value.
   11074                 :            :  *
   11075                 :            :  * @param[in, out] key
   11076                 :            :  *   Flow matcher value.
   11077                 :            :  * @param[in] item
   11078                 :            :  *   Flow pattern to translate.
   11079                 :            :  * @param[in] inner
   11080                 :            :  *   Item is inner pattern.
   11081                 :            :  * @param[in] key_type
   11082                 :            :  *   Set flow matcher mask or value.
   11083                 :            :  */
   11084                 :            : static void
   11085                 :          0 : flow_dv_translate_item_icmp6(void *key, const struct rte_flow_item *item,
   11086                 :            :                              int inner, uint32_t key_type)
   11087                 :            : {
   11088                 :            :         const struct rte_flow_item_icmp6 *icmp6_m;
   11089                 :            :         const struct rte_flow_item_icmp6 *icmp6_v;
   11090                 :            :         void *headers_v;
   11091                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11092                 :            : 
   11093         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11094                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11095         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11096         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xFF);
   11097                 :            :         else
   11098         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
   11099                 :            :                          IPPROTO_ICMPV6);
   11100   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11101                 :            :                 return;
   11102   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp6_v, icmp6_m,
             #  #  #  # ]
   11103                 :            :                 &rte_flow_item_icmp6_mask);
   11104         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type,
   11105                 :            :                  icmp6_v->type & icmp6_m->type);
   11106         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code,
   11107                 :            :                  icmp6_v->code & icmp6_m->code);
   11108                 :            : }
   11109                 :            : 
   11110                 :            : /**
   11111                 :            :  * Add ICMP6 echo request/reply item to the value.
   11112                 :            :  *
   11113                 :            :  * @param[in, out] key
   11114                 :            :  *   Flow matcher value.
   11115                 :            :  * @param[in] item
   11116                 :            :  *   Flow pattern to translate.
   11117                 :            :  * @param[in] inner
   11118                 :            :  *   Item is inner pattern.
   11119                 :            :  * @param[in] key_type
   11120                 :            :  *   Set flow matcher mask or value.
   11121                 :            :  */
   11122                 :            : static void
   11123         [ #  # ]:          0 : flow_dv_translate_item_icmp6_echo(void *key, const struct rte_flow_item *item,
   11124                 :            :                                   int inner, uint32_t key_type)
   11125                 :            : {
   11126                 :            :         const struct rte_flow_item_icmp6_echo *icmp6_m;
   11127                 :            :         const struct rte_flow_item_icmp6_echo *icmp6_v;
   11128                 :            :         uint32_t icmp6_header_data_m = 0;
   11129                 :            :         uint32_t icmp6_header_data_v = 0;
   11130                 :            :         void *headers_v;
   11131                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11132                 :            :         uint8_t icmp6_type = 0;
   11133                 :            :         struct rte_flow_item_icmp6_echo zero_mask;
   11134                 :            : 
   11135                 :            :         memset(&zero_mask, 0, sizeof(zero_mask));
   11136         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11137                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11138         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11139         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xFF);
   11140                 :            :         else
   11141         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
   11142                 :            :                          IPPROTO_ICMPV6);
   11143   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp6_v, icmp6_m, &zero_mask);
             #  #  #  # ]
   11144                 :            :         /* Set fixed type and code for icmpv6 echo request or reply */
   11145         [ #  # ]:          0 :         icmp6_type = (item->type == RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST ?
   11146                 :            :                       RTE_ICMP6_ECHO_REQUEST : RTE_ICMP6_ECHO_REPLY);
   11147         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   11148         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, 0xFF);
   11149         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 0xFF);
   11150                 :            :         } else {
   11151         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, icmp6_type);
   11152         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 0);
   11153                 :            :         }
   11154         [ #  # ]:          0 :         if (icmp6_v == NULL)
   11155                 :          0 :                 return;
   11156                 :            :         /* Set icmp6 header data (identifier & sequence) accordingly */
   11157                 :          0 :         icmp6_header_data_m =
   11158         [ #  # ]:          0 :                 (rte_be_to_cpu_16(icmp6_m->hdr.identifier) << 16) |
   11159         [ #  # ]:          0 :                 rte_be_to_cpu_16(icmp6_m->hdr.sequence);
   11160         [ #  # ]:          0 :         if (icmp6_header_data_m) {
   11161                 :          0 :                 icmp6_header_data_v =
   11162         [ #  # ]:          0 :                         (rte_be_to_cpu_16(icmp6_v->hdr.identifier) << 16) |
   11163         [ #  # ]:          0 :                         rte_be_to_cpu_16(icmp6_v->hdr.sequence);
   11164         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_header_data,
   11165                 :            :                          icmp6_header_data_v & icmp6_header_data_m);
   11166                 :            :         }
   11167                 :            : }
   11168                 :            : 
   11169                 :            : /**
   11170                 :            :  * Add ICMP item to the value.
   11171                 :            :  *
   11172                 :            :  * @param[in, out] key
   11173                 :            :  *   Flow matcher value.
   11174                 :            :  * @param[in] item
   11175                 :            :  *   Flow pattern to translate.
   11176                 :            :  * @param[in] inner
   11177                 :            :  *   Item is inner pattern.
   11178                 :            :  * @param[in] key_type
   11179                 :            :  *   Set flow matcher mask or value.
   11180                 :            :  */
   11181                 :            : static void
   11182                 :          0 : flow_dv_translate_item_icmp(void *key, const struct rte_flow_item *item,
   11183                 :            :                             int inner, uint32_t key_type)
   11184                 :            : {
   11185                 :            :         const struct rte_flow_item_icmp *icmp_m;
   11186                 :            :         const struct rte_flow_item_icmp *icmp_v;
   11187                 :            :         uint32_t icmp_header_data_m = 0;
   11188                 :            :         uint32_t icmp_header_data_v = 0;
   11189                 :            :         void *headers_v;
   11190                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11191                 :            : 
   11192         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11193                 :            :                         MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11194         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11195         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11196                 :            :                          ip_protocol, 0xFF);
   11197                 :            :         else
   11198         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11199                 :            :                          ip_protocol, IPPROTO_ICMP);
   11200   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11201                 :            :                 return;
   11202   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp_v, icmp_m,
             #  #  #  # ]
   11203                 :            :                 &rte_flow_item_icmp_mask);
   11204         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmp_type,
   11205                 :            :                  icmp_v->hdr.icmp_type & icmp_m->hdr.icmp_type);
   11206         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmp_code,
   11207                 :            :                  icmp_v->hdr.icmp_code & icmp_m->hdr.icmp_code);
   11208         [ #  # ]:          0 :         icmp_header_data_m = rte_be_to_cpu_16(icmp_m->hdr.icmp_seq_nb);
   11209         [ #  # ]:          0 :         icmp_header_data_m |= rte_be_to_cpu_16(icmp_m->hdr.icmp_ident) << 16;
   11210         [ #  # ]:          0 :         if (icmp_header_data_m) {
   11211         [ #  # ]:          0 :                 icmp_header_data_v = rte_be_to_cpu_16(icmp_v->hdr.icmp_seq_nb);
   11212                 :          0 :                 icmp_header_data_v |=
   11213         [ #  # ]:          0 :                          rte_be_to_cpu_16(icmp_v->hdr.icmp_ident) << 16;
   11214         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmp_header_data,
   11215                 :            :                          icmp_header_data_v & icmp_header_data_m);
   11216                 :            :         }
   11217                 :            : }
   11218                 :            : 
   11219                 :            : /**
   11220                 :            :  * Add GTP item to the value.
   11221                 :            :  *
   11222                 :            :  * @param[in, out] key
   11223                 :            :  *   Flow matcher value.
   11224                 :            :  * @param[in] item
   11225                 :            :  *   Flow pattern to translate.
   11226                 :            :  * @param[in] inner
   11227                 :            :  *   Item is inner pattern.
   11228                 :            :  * @param[in] key_type
   11229                 :            :  *   Set flow matcher mask or value.
   11230                 :            :  */
   11231                 :            : static void
   11232                 :          0 : flow_dv_translate_item_gtp(void *key, const struct rte_flow_item *item,
   11233                 :            :                            int inner, uint32_t key_type)
   11234                 :            : {
   11235                 :            :         const struct rte_flow_item_gtp *gtp_m;
   11236                 :            :         const struct rte_flow_item_gtp *gtp_v;
   11237                 :            :         void *headers_v;
   11238                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11239                 :            :         uint16_t dport = RTE_GTPU_UDP_PORT;
   11240                 :            : 
   11241         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11242                 :            :                         MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11243   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   11244         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   11245         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11246                 :            :                                  udp_dport, 0xFFFF);
   11247                 :            :                 else
   11248         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11249                 :            :                                  udp_dport, dport);
   11250                 :            :         }
   11251   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11252                 :            :                 return;
   11253   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, gtp_v, gtp_m,
             #  #  #  # ]
   11254                 :            :                 &rte_flow_item_gtp_mask);
   11255         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags,
   11256                 :            :                  gtp_v->hdr.gtp_hdr_info & gtp_m->hdr.gtp_hdr_info);
   11257         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_type,
   11258                 :            :                  gtp_v->hdr.msg_type & gtp_m->hdr.msg_type);
   11259   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_teid,
   11260                 :            :                  rte_be_to_cpu_32(gtp_v->hdr.teid & gtp_m->hdr.teid));
   11261                 :            : }
   11262                 :            : 
   11263                 :            : /**
   11264                 :            :  * Add GTP PSC item to matcher.
   11265                 :            :  *
   11266                 :            :  * @param[in, out] key
   11267                 :            :  *   Flow matcher value.
   11268                 :            :  * @param[in] item
   11269                 :            :  *   Flow pattern to translate.
   11270                 :            :  * @param[in] key_type
   11271                 :            :  *   Set flow matcher mask or value.
   11272                 :            :  */
   11273                 :            : static int
   11274                 :          0 : flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
   11275                 :            :                                uint32_t key_type)
   11276                 :            : {
   11277                 :            :         const struct rte_flow_item_gtp_psc *gtp_psc_m;
   11278                 :            :         const struct rte_flow_item_gtp_psc *gtp_psc_v;
   11279                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11280                 :            :         union {
   11281                 :            :                 uint32_t w32;
   11282                 :            :                 struct {
   11283                 :            :                         uint16_t seq_num;
   11284                 :            :                         uint8_t npdu_num;
   11285                 :            :                         uint8_t next_ext_header_type;
   11286                 :            :                 };
   11287                 :            :         } dw_2;
   11288                 :            :         union {
   11289                 :            :                 uint32_t w32;
   11290                 :            :                 struct {
   11291                 :            :                         uint8_t len;
   11292                 :            :                         uint8_t type_flags;
   11293                 :            :                         uint8_t qfi;
   11294                 :            :                         uint8_t reserved;
   11295                 :            :                 };
   11296                 :            :         } dw_0;
   11297                 :            :         uint8_t gtp_flags;
   11298                 :            : 
   11299                 :            :         /* Always set E-flag match on one, regardless of GTP item settings. */
   11300         [ #  # ]:          0 :         gtp_flags = MLX5_GET(fte_match_set_misc3, misc3_v, gtpu_msg_flags);
   11301                 :          0 :         gtp_flags |= MLX5_GTP_EXT_HEADER_FLAG;
   11302         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags, gtp_flags);
   11303                 :            :         /*Set next extension header type. */
   11304                 :          0 :         dw_2.seq_num = 0;
   11305                 :          0 :         dw_2.npdu_num = 0;
   11306         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11307                 :          0 :                 dw_2.next_ext_header_type = 0xff;
   11308                 :            :         else
   11309                 :          0 :                 dw_2.next_ext_header_type = 0x85;
   11310   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_dw_2,
   11311                 :            :                  rte_cpu_to_be_32(dw_2.w32));
   11312   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11313                 :            :                 return 0;
   11314   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, gtp_psc_v,
             #  #  #  # ]
   11315                 :            :                 gtp_psc_m, &rte_flow_item_gtp_psc_mask);
   11316                 :          0 :         dw_0.w32 = 0;
   11317                 :          0 :         dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->hdr.type &
   11318                 :            :                                                   gtp_psc_m->hdr.type);
   11319                 :          0 :         dw_0.qfi = gtp_psc_v->hdr.qfi & gtp_psc_m->hdr.qfi;
   11320   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_first_ext_dw_0,
   11321                 :            :                  rte_cpu_to_be_32(dw_0.w32));
   11322                 :          0 :         return 0;
   11323                 :            : }
   11324                 :            : 
   11325                 :            : /**
   11326                 :            :  * Add eCPRI item to matcher and to the value.
   11327                 :            :  *
   11328                 :            :  * @param[in] dev
   11329                 :            :  *   The devich to configure through.
   11330                 :            :  * @param[in, out] key
   11331                 :            :  *   Flow matcher value.
   11332                 :            :  * @param[in] item
   11333                 :            :  *   Flow pattern to translate.
   11334                 :            :  * @param[in] last_item
   11335                 :            :  *   Last item flags.
   11336                 :            :  * @param[in] key_type
   11337                 :            :  *   Set flow matcher mask or value.
   11338                 :            :  */
   11339                 :            : static void
   11340                 :          0 : flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
   11341                 :            :                              const struct rte_flow_item *item,
   11342                 :            :                              uint64_t last_item, uint32_t key_type)
   11343                 :            : {
   11344                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11345                 :            :         const struct rte_flow_item_ecpri *ecpri_m;
   11346                 :            :         const struct rte_flow_item_ecpri *ecpri_v;
   11347                 :          0 :         const struct rte_flow_item_ecpri *ecpri_vv = item->spec;
   11348                 :            :         struct rte_ecpri_common_hdr common;
   11349                 :            :         void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4);
   11350                 :            :         uint32_t *samples;
   11351                 :            :         void *dw_v;
   11352                 :            : 
   11353                 :            :         /*
   11354                 :            :          * In case of eCPRI over Ethernet, if EtherType is not specified,
   11355                 :            :          * match on eCPRI EtherType implicitly.
   11356                 :            :          */
   11357         [ #  # ]:          0 :         if (last_item & MLX5_FLOW_LAYER_OUTER_L2) {
   11358                 :            :                 void *hdrs_v, *l2v;
   11359                 :            : 
   11360                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11361                 :            :                 l2v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
   11362         [ #  # ]:          0 :                 if (*(uint16_t *)l2v == 0) {
   11363         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   11364                 :          0 :                                 *(uint16_t *)l2v = UINT16_MAX;
   11365                 :            :                         else
   11366                 :          0 :                                 *(uint16_t *)l2v =
   11367                 :            :                                         RTE_BE16(RTE_ETHER_TYPE_ECPRI);
   11368                 :            :                 }
   11369                 :            :         }
   11370   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11371                 :          0 :                 return;
   11372   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m,
             #  #  #  # ]
   11373                 :            :                 &rte_flow_item_ecpri_mask);
   11374                 :            :         /*
   11375                 :            :          * Maximal four DW samples are supported in a single matching now.
   11376                 :            :          * Two are used now for a eCPRI matching:
   11377                 :            :          * 1. Type: one byte, mask should be 0x00ff0000 in network order
   11378                 :            :          * 2. ID of a message: one or two bytes, mask 0xffff0000 or 0xff000000
   11379                 :            :          *    if any.
   11380                 :            :          */
   11381         [ #  # ]:          0 :         if (!ecpri_m->hdr.common.u32)
   11382                 :            :                 return;
   11383                 :          0 :         samples = priv->sh->ecpri_parser.ids;
   11384                 :            :         /* Need to take the whole DW as the mask to fill the entry. */
   11385                 :            :         dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
   11386                 :            :                             prog_sample_field_value_0);
   11387                 :            :         /* Already big endian (network order) in the header. */
   11388                 :          0 :         *(uint32_t *)dw_v = ecpri_v->hdr.common.u32 & ecpri_m->hdr.common.u32;
   11389                 :            :         /* Sample#0, used for matching type, offset 0. */
   11390                 :            :         /* It makes no sense to set the sample ID in the mask field. */
   11391         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc4, misc4_v,
   11392                 :            :                  prog_sample_field_id_0, samples[0]);
   11393                 :            :         /*
   11394                 :            :          * Checking if message body part needs to be matched.
   11395                 :            :          * Some wildcard rules only matching type field should be supported.
   11396                 :            :          */
   11397         [ #  # ]:          0 :         if (ecpri_m->hdr.dummy[0]) {
   11398         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M)
   11399         [ #  # ]:          0 :                         common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
   11400                 :            :                 else
   11401         [ #  # ]:          0 :                         common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
   11402         [ #  # ]:          0 :                 switch (common.type) {
   11403                 :          0 :                 case RTE_ECPRI_MSG_TYPE_IQ_DATA:
   11404                 :            :                 case RTE_ECPRI_MSG_TYPE_RTC_CTRL:
   11405                 :            :                 case RTE_ECPRI_MSG_TYPE_DLY_MSR:
   11406                 :            :                         dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
   11407                 :            :                                             prog_sample_field_value_1);
   11408                 :          0 :                         *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] &
   11409                 :            :                                             ecpri_m->hdr.dummy[0];
   11410                 :            :                         /* Sample#1, to match message body, offset 4. */
   11411         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_misc4, misc4_v,
   11412                 :            :                                  prog_sample_field_id_1, samples[1]);
   11413                 :          0 :                         break;
   11414                 :            :                 default:
   11415                 :            :                         /* Others, do not match any sample ID. */
   11416                 :            :                         break;
   11417                 :            :                 }
   11418                 :            :         }
   11419                 :            : }
   11420                 :            : 
   11421                 :            : /*
   11422                 :            :  * Add connection tracking status item to matcher
   11423                 :            :  *
   11424                 :            :  * @param[in] dev
   11425                 :            :  *   The devich to configure through.
   11426                 :            :  * @param[in, out] matcher
   11427                 :            :  *   Flow matcher.
   11428                 :            :  * @param[in, out] key
   11429                 :            :  *   Flow matcher value.
   11430                 :            :  * @param[in] item
   11431                 :            :  *   Flow pattern to translate.
   11432                 :            :  */
   11433                 :            : static void
   11434                 :          0 : flow_dv_translate_item_aso_ct(struct rte_eth_dev *dev,
   11435                 :            :                               void *matcher, void *key,
   11436                 :            :                               const struct rte_flow_item *item)
   11437                 :            : {
   11438                 :            :         uint32_t reg_value = 0;
   11439                 :            :         int reg_id;
   11440                 :            :         /* 8LSB 0b 11/0000/11, middle 4 bits are reserved. */
   11441                 :            :         uint32_t reg_mask = 0;
   11442                 :          0 :         const struct rte_flow_item_conntrack *spec = item->spec;
   11443                 :          0 :         const struct rte_flow_item_conntrack *mask = item->mask;
   11444                 :            :         uint32_t flags;
   11445                 :            :         struct rte_flow_error error;
   11446                 :            : 
   11447         [ #  # ]:          0 :         if (!mask)
   11448                 :            :                 mask = &rte_flow_item_conntrack_mask;
   11449   [ #  #  #  # ]:          0 :         if (!spec || !mask->flags)
   11450                 :          0 :                 return;
   11451                 :          0 :         flags = spec->flags & mask->flags;
   11452                 :            :         /* The conflict should be checked in the validation. */
   11453                 :            :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_VALID)
   11454                 :            :                 reg_value |= MLX5_CT_SYNDROME_VALID;
   11455         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
   11456                 :            :                 reg_value |= MLX5_CT_SYNDROME_STATE_CHANGE;
   11457         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_INVALID)
   11458                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_INVALID;
   11459         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED)
   11460                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_TRAP;
   11461         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
   11462                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_BAD_PACKET;
   11463         [ #  # ]:          0 :         if (mask->flags & (RTE_FLOW_CONNTRACK_PKT_STATE_VALID |
   11464                 :            :                            RTE_FLOW_CONNTRACK_PKT_STATE_INVALID |
   11465                 :            :                            RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED))
   11466                 :            :                 reg_mask |= 0xc0;
   11467         [ #  # ]:          0 :         if (mask->flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
   11468                 :          0 :                 reg_mask |= MLX5_CT_SYNDROME_STATE_CHANGE;
   11469         [ #  # ]:          0 :         if (mask->flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
   11470                 :          0 :                 reg_mask |= MLX5_CT_SYNDROME_BAD_PACKET;
   11471                 :            :         /* The REG_C_x value could be saved during startup. */
   11472                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, &error);
   11473         [ #  # ]:          0 :         if (reg_id == REG_NON)
   11474                 :            :                 return;
   11475                 :          0 :         flow_dv_match_meta_reg_all(matcher, key, (enum modify_reg)reg_id,
   11476                 :            :                                reg_value, reg_mask);
   11477                 :            : }
   11478                 :            : 
   11479                 :            : static void
   11480                 :          0 : flow_dv_translate_item_flex(struct rte_eth_dev *dev, void *matcher, void *key,
   11481                 :            :                             const struct rte_flow_item *item,
   11482                 :            :                             struct mlx5_flow *dev_flow, bool is_inner)
   11483                 :            : {
   11484                 :          0 :         const struct rte_flow_item_flex *spec =
   11485                 :            :                 (const struct rte_flow_item_flex *)item->spec;
   11486                 :          0 :         int index = mlx5_flex_acquire_index(dev, spec->handle, false);
   11487                 :            : 
   11488                 :            :         MLX5_ASSERT(index >= 0 && index < (int)(sizeof(uint32_t) * CHAR_BIT));
   11489         [ #  # ]:          0 :         if (index < 0)
   11490                 :            :                 return;
   11491         [ #  # ]:          0 :         if (!(dev_flow->handle->flex_item & RTE_BIT32(index))) {
   11492                 :            :                 /* Don't count both inner and outer flex items in one rule. */
   11493                 :          0 :                 if (mlx5_flex_acquire_index(dev, spec->handle, true) != index)
   11494                 :            :                         MLX5_ASSERT(false);
   11495                 :          0 :                 dev_flow->handle->flex_item |= (uint8_t)RTE_BIT32(index);
   11496                 :            :         }
   11497                 :          0 :         mlx5_flex_flow_translate_item(dev, matcher, key, item, is_inner);
   11498                 :            : }
   11499                 :            : 
   11500                 :            : /**
   11501                 :            :  * Add METER_COLOR item to matcher
   11502                 :            :  *
   11503                 :            :  * @param[in] dev
   11504                 :            :  *   The device to configure through.
   11505                 :            :  * @param[in, out] key
   11506                 :            :  *   Flow matcher value.
   11507                 :            :  * @param[in] item
   11508                 :            :  *   Flow pattern to translate.
   11509                 :            :  * @param[in] key_type
   11510                 :            :  *   Set flow matcher mask or value.
   11511                 :            :  */
   11512                 :            : static void
   11513                 :          0 : flow_dv_translate_item_meter_color(struct rte_eth_dev *dev, void *key,
   11514                 :            :                             const struct rte_flow_item *item,
   11515                 :            :                             uint32_t key_type)
   11516                 :            : {
   11517                 :          0 :         const struct rte_flow_item_meter_color *color_m = item->mask;
   11518                 :          0 :         const struct rte_flow_item_meter_color *color_v = item->spec;
   11519                 :            :         uint32_t value, mask;
   11520                 :            :         int reg = REG_NON;
   11521                 :            : 
   11522                 :            :         MLX5_ASSERT(color_v);
   11523   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11524                 :            :                 return;
   11525   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, color_v, color_m,
             #  #  #  # ]
   11526                 :            :                 &rte_flow_item_meter_color_mask);
   11527         [ #  # ]:          0 :         value = rte_col_2_mlx5_col(color_v->color);
   11528                 :            :         mask = color_m ?
   11529         [ #  # ]:          0 :                 color_m->color : (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
   11530         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   11531                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
   11532                 :            :         else
   11533                 :            :                 reg = flow_hw_get_reg_id(dev,
   11534                 :            :                                          RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
   11535         [ #  # ]:          0 :         if (reg == REG_NON)
   11536                 :            :                 return;
   11537                 :          0 :         flow_dv_match_meta_reg(key, (enum modify_reg)reg, value, mask);
   11538                 :            : }
   11539                 :            : 
   11540                 :            : static void
   11541                 :          0 : flow_dv_translate_item_aggr_affinity(void *key,
   11542                 :            :                                     const struct rte_flow_item *item,
   11543                 :            :                                     uint32_t key_type)
   11544                 :            : {
   11545                 :            :         const struct rte_flow_item_aggr_affinity *affinity_v;
   11546                 :            :         const struct rte_flow_item_aggr_affinity *affinity_m;
   11547                 :            :         void *misc_v;
   11548                 :            : 
   11549   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, affinity_v, affinity_m,
             #  #  #  # ]
   11550                 :            :                          &rte_flow_item_aggr_affinity_mask);
   11551                 :            :         misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   11552         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, lag_rx_port_affinity,
   11553                 :            :                  affinity_v->affinity & affinity_m->affinity);
   11554                 :          0 : }
   11555                 :            : 
   11556                 :            : static void
   11557                 :          0 : flow_dv_translate_item_ib_bth(void *key,
   11558                 :            :                               const struct rte_flow_item *item,
   11559                 :            :                               int inner, uint32_t key_type)
   11560                 :            : {
   11561                 :            :         const struct rte_flow_item_ib_bth *bth_m;
   11562                 :            :         const struct rte_flow_item_ib_bth *bth_v;
   11563                 :            :         void *headers_v, *misc_v;
   11564                 :            :         uint16_t udp_dport;
   11565                 :            :         char *qpn_v;
   11566                 :            :         int i, size;
   11567                 :            : 
   11568         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11569                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11570   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   11571         [ #  # ]:          0 :                 udp_dport = key_type & MLX5_SET_MATCHER_M ?
   11572                 :            :                         0xFFFF : MLX5_UDP_PORT_ROCEv2;
   11573         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, udp_dport);
   11574                 :            :         }
   11575   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11576                 :            :                 return;
   11577   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, bth_v, bth_m, &rte_flow_item_ib_bth_mask);
             #  #  #  # ]
   11578                 :            :         misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   11579         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, bth_opcode,
   11580                 :            :                  bth_v->hdr.opcode & bth_m->hdr.opcode);
   11581                 :          0 :         qpn_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, bth_dst_qp);
   11582                 :            :         size = sizeof(bth_m->hdr.dst_qp);
   11583         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   11584                 :          0 :                 qpn_v[i] = bth_m->hdr.dst_qp[i] & bth_v->hdr.dst_qp[i];
   11585                 :            : }
   11586                 :            : 
   11587                 :            : static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
   11588                 :            : 
   11589                 :            : #define HEADER_IS_ZERO(match_criteria, headers)                              \
   11590                 :            :         !(memcmp(MLX5_ADDR_OF(fte_match_param, match_criteria, headers),     \
   11591                 :            :                  matcher_zero, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \
   11592                 :            : 
   11593                 :            : /**
   11594                 :            :  * Calculate flow matcher enable bitmap.
   11595                 :            :  *
   11596                 :            :  * @param match_criteria
   11597                 :            :  *   Pointer to flow matcher criteria.
   11598                 :            :  *
   11599                 :            :  * @return
   11600                 :            :  *   Bitmap of enabled fields.
   11601                 :            :  */
   11602                 :            : static uint8_t
   11603                 :          0 : flow_dv_matcher_enable(uint32_t *match_criteria)
   11604                 :            : {
   11605                 :            :         uint8_t match_criteria_enable;
   11606                 :            : 
   11607                 :            :         match_criteria_enable =
   11608                 :          0 :                 (!HEADER_IS_ZERO(match_criteria, outer_headers)) <<
   11609                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_OUTER_BIT;
   11610                 :          0 :         match_criteria_enable |=
   11611         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters)) <<
   11612                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC_BIT;
   11613                 :          0 :         match_criteria_enable |=
   11614         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, inner_headers)) <<
   11615                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_INNER_BIT;
   11616                 :          0 :         match_criteria_enable |=
   11617         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) <<
   11618                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT;
   11619                 :          0 :         match_criteria_enable |=
   11620         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_3)) <<
   11621                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC3_BIT;
   11622                 :          0 :         match_criteria_enable |=
   11623         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_4)) <<
   11624                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT;
   11625                 :          0 :         match_criteria_enable |=
   11626         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_5)) <<
   11627                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC5_BIT;
   11628                 :          0 :         return match_criteria_enable;
   11629                 :            : }
   11630                 :            : 
   11631                 :            : static void
   11632                 :            : __flow_dv_adjust_buf_size(size_t *size, uint8_t match_criteria)
   11633                 :            : {
   11634                 :            :         /*
   11635                 :            :          * Check flow matching criteria first, subtract misc5/4 length if flow
   11636                 :            :          * doesn't own misc5/4 parameters. In some old rdma-core releases,
   11637                 :            :          * misc5/4 are not supported, and matcher creation failure is expected
   11638                 :            :          * w/o subtraction. If misc5 is provided, misc4 must be counted in since
   11639                 :            :          * misc5 is right after misc4.
   11640                 :            :          */
   11641                 :          0 :         if (!(match_criteria & (1 << MLX5_MATCH_CRITERIA_ENABLE_MISC5_BIT))) {
   11642                 :          0 :                 *size = MLX5_ST_SZ_BYTES(fte_match_param) -
   11643                 :            :                         MLX5_ST_SZ_BYTES(fte_match_set_misc5);
   11644   [ #  #  #  #  :          0 :                 if (!(match_criteria & (1 <<
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
   11645                 :            :                         MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT))) {
   11646                 :          0 :                         *size -= MLX5_ST_SZ_BYTES(fte_match_set_misc4);
   11647                 :            :                 }
   11648                 :            :         }
   11649                 :            : }
   11650                 :            : 
   11651                 :            : struct mlx5_list_entry *
   11652                 :          0 : flow_matcher_clone_cb(void *tool_ctx __rte_unused,
   11653                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
   11654                 :            : {
   11655                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11656                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11657                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(ref->tbl,
   11658                 :            :                                                             typeof(*tbl), tbl);
   11659                 :          0 :         struct mlx5_flow_dv_matcher *resource = mlx5_malloc(MLX5_MEM_ANY,
   11660                 :            :                                                             sizeof(*resource),
   11661                 :            :                                                             0, SOCKET_ID_ANY);
   11662                 :            : 
   11663         [ #  # ]:          0 :         if (!resource) {
   11664                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11665                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11666                 :            :                                    "cannot create matcher");
   11667                 :          0 :                 return NULL;
   11668                 :            :         }
   11669                 :            :         memcpy(resource, entry, sizeof(*resource));
   11670                 :          0 :         resource->tbl = &tbl->tbl;
   11671                 :          0 :         return &resource->entry;
   11672                 :            : }
   11673                 :            : 
   11674                 :            : void
   11675                 :          0 : flow_matcher_clone_free_cb(void *tool_ctx __rte_unused,
   11676                 :            :                              struct mlx5_list_entry *entry)
   11677                 :            : {
   11678                 :          0 :         mlx5_free(entry);
   11679                 :          0 : }
   11680                 :            : 
   11681                 :            : struct mlx5_list_entry *
   11682                 :          0 : flow_dv_tbl_create_cb(void *tool_ctx, void *cb_ctx)
   11683                 :          0 : {
   11684                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11685                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11686                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   11687                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11688                 :          0 :         struct mlx5_flow_tbl_tunnel_prm *tt_prm = ctx->data2;
   11689                 :          0 :         struct rte_flow_error *error = ctx->error;
   11690                 :          0 :         union mlx5_flow_tbl_key key = { .v64 = *(uint64_t *)(ctx->data) };
   11691                 :            :         struct mlx5_flow_tbl_resource *tbl;
   11692                 :            :         void *domain;
   11693                 :          0 :         uint32_t idx = 0;
   11694                 :            :         int ret;
   11695                 :            : 
   11696                 :          0 :         tbl_data = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_JUMP], &idx);
   11697         [ #  # ]:          0 :         if (!tbl_data) {
   11698                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11699                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11700                 :            :                                    NULL,
   11701                 :            :                                    "cannot allocate flow table data entry");
   11702                 :          0 :                 return NULL;
   11703                 :            :         }
   11704                 :          0 :         tbl_data->idx = idx;
   11705                 :          0 :         tbl_data->tunnel = tt_prm->tunnel;
   11706                 :          0 :         tbl_data->group_id = tt_prm->group_id;
   11707         [ #  # ]:          0 :         tbl_data->external = !!tt_prm->external;
   11708                 :          0 :         tbl_data->tunnel_offload = is_tunnel_offload_active(dev);
   11709                 :          0 :         tbl_data->is_egress = !!key.is_egress;
   11710                 :          0 :         tbl_data->is_transfer = !!key.is_fdb;
   11711                 :          0 :         tbl_data->dummy = !!key.dummy;
   11712                 :          0 :         tbl_data->level = key.level;
   11713                 :          0 :         tbl_data->id = key.id;
   11714                 :            :         tbl = &tbl_data->tbl;
   11715         [ #  # ]:          0 :         if (key.dummy)
   11716                 :          0 :                 return &tbl_data->entry;
   11717         [ #  # ]:          0 :         if (key.is_fdb)
   11718                 :          0 :                 domain = sh->fdb_domain;
   11719         [ #  # ]:          0 :         else if (key.is_egress)
   11720                 :          0 :                 domain = sh->tx_domain;
   11721                 :            :         else
   11722                 :          0 :                 domain = sh->rx_domain;
   11723                 :            :         ret = mlx5_flow_os_create_flow_tbl(domain, key.level, &tbl->obj);
   11724                 :            :         if (ret) {
   11725                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11726                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11727                 :            :                                    NULL, "cannot create flow table object");
   11728                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11729                 :          0 :                 return NULL;
   11730                 :            :         }
   11731         [ #  # ]:          0 :         if (key.level != 0) {
   11732                 :            :                 ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
   11733                 :            :                                         (tbl->obj, &tbl_data->jump.action);
   11734                 :            :                 if (ret) {
   11735                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   11736                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11737                 :            :                                            NULL,
   11738                 :            :                                            "cannot create flow jump action");
   11739                 :          0 :                         mlx5_flow_os_destroy_flow_tbl(tbl->obj);
   11740                 :          0 :                         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11741                 :          0 :                         return NULL;
   11742                 :            :                 }
   11743                 :            :         }
   11744   [ #  #  #  # ]:          0 :         MKSTR(matcher_name, "%s_%s_%u_%u_matcher_list",
   11745                 :            :               key.is_fdb ? "FDB" : "NIC", key.is_egress ? "egress" : "ingress",
   11746                 :            :               key.level, key.id);
   11747                 :          0 :         tbl_data->matchers = mlx5_list_create(matcher_name, sh, true,
   11748                 :            :                                               flow_matcher_create_cb,
   11749                 :            :                                               flow_matcher_match_cb,
   11750                 :            :                                               flow_matcher_remove_cb,
   11751                 :            :                                               flow_matcher_clone_cb,
   11752                 :            :                                               flow_matcher_clone_free_cb);
   11753         [ #  # ]:          0 :         if (!tbl_data->matchers) {
   11754                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11755                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11756                 :            :                                    NULL,
   11757                 :            :                                    "cannot create tbl matcher list");
   11758                 :          0 :                 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action);
   11759                 :          0 :                 mlx5_flow_os_destroy_flow_tbl(tbl->obj);
   11760                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11761                 :          0 :                 return NULL;
   11762                 :            :         }
   11763                 :          0 :         return &tbl_data->entry;
   11764                 :            : }
   11765                 :            : 
   11766                 :            : int
   11767                 :          0 : flow_dv_tbl_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
   11768                 :            :                      void *cb_ctx)
   11769                 :            : {
   11770                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11771                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11772                 :            :                 container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11773                 :          0 :         union mlx5_flow_tbl_key key = { .v64 =  *(uint64_t *)(ctx->data) };
   11774                 :            : 
   11775                 :          0 :         return tbl_data->level != key.level ||
   11776         [ #  # ]:          0 :                tbl_data->id != key.id ||
   11777         [ #  # ]:          0 :                tbl_data->dummy != key.dummy ||
   11778   [ #  #  #  # ]:          0 :                tbl_data->is_transfer != !!key.is_fdb ||
   11779         [ #  # ]:          0 :                tbl_data->is_egress != !!key.is_egress;
   11780                 :            : }
   11781                 :            : 
   11782                 :            : struct mlx5_list_entry *
   11783                 :          0 : flow_dv_tbl_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
   11784                 :            :                       void *cb_ctx)
   11785                 :            : {
   11786                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11787                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11788                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11789                 :          0 :         struct rte_flow_error *error = ctx->error;
   11790                 :          0 :         uint32_t idx = 0;
   11791                 :            : 
   11792                 :          0 :         tbl_data = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_JUMP], &idx);
   11793         [ #  # ]:          0 :         if (!tbl_data) {
   11794                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11795                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11796                 :            :                                    NULL,
   11797                 :            :                                    "cannot allocate flow table data entry");
   11798                 :          0 :                 return NULL;
   11799                 :            :         }
   11800                 :            :         memcpy(tbl_data, oentry, sizeof(*tbl_data));
   11801                 :          0 :         tbl_data->idx = idx;
   11802                 :          0 :         return &tbl_data->entry;
   11803                 :            : }
   11804                 :            : 
   11805                 :            : void
   11806                 :          0 : flow_dv_tbl_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11807                 :            : {
   11808                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11809                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11810                 :            :                     container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11811                 :            : 
   11812                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx);
   11813                 :          0 : }
   11814                 :            : 
   11815                 :            : /**
   11816                 :            :  * Get a flow table.
   11817                 :            :  *
   11818                 :            :  * @param[in, out] dev
   11819                 :            :  *   Pointer to rte_eth_dev structure.
   11820                 :            :  * @param[in] table_level
   11821                 :            :  *   Table level to use.
   11822                 :            :  * @param[in] egress
   11823                 :            :  *   Direction of the table.
   11824                 :            :  * @param[in] transfer
   11825                 :            :  *   E-Switch or NIC flow.
   11826                 :            :  * @param[in] dummy
   11827                 :            :  *   Dummy entry for dv API.
   11828                 :            :  * @param[in] table_id
   11829                 :            :  *   Table id to use.
   11830                 :            :  * @param[out] error
   11831                 :            :  *   pointer to error structure.
   11832                 :            :  *
   11833                 :            :  * @return
   11834                 :            :  *   Returns tables resource based on the index, NULL in case of failed.
   11835                 :            :  */
   11836                 :            : struct mlx5_flow_tbl_resource *
   11837                 :          0 : flow_dv_tbl_resource_get(struct rte_eth_dev *dev,
   11838                 :            :                          uint32_t table_level, uint8_t egress,
   11839                 :            :                          uint8_t transfer,
   11840                 :            :                          bool external,
   11841                 :            :                          const struct mlx5_flow_tunnel *tunnel,
   11842                 :            :                          uint32_t group_id, uint8_t dummy,
   11843                 :            :                          uint32_t table_id,
   11844                 :            :                          struct rte_flow_error *error)
   11845                 :            : {
   11846                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11847                 :          0 :         union mlx5_flow_tbl_key table_key = {
   11848                 :            :                 {
   11849                 :            :                         .level = table_level,
   11850                 :            :                         .id = table_id,
   11851                 :            :                         .reserved = 0,
   11852                 :          0 :                         .dummy = !!dummy,
   11853                 :          0 :                         .is_fdb = !!transfer,
   11854                 :          0 :                         .is_egress = !!egress,
   11855                 :            :                 }
   11856                 :            :         };
   11857                 :          0 :         struct mlx5_flow_tbl_tunnel_prm tt_prm = {
   11858                 :            :                 .tunnel = tunnel,
   11859                 :            :                 .group_id = group_id,
   11860                 :            :                 .external = external,
   11861                 :            :         };
   11862                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   11863                 :            :                 .dev = dev,
   11864                 :            :                 .error = error,
   11865                 :            :                 .data = &table_key.v64,
   11866                 :            :                 .data2 = &tt_prm,
   11867                 :            :         };
   11868                 :            :         struct mlx5_list_entry *entry;
   11869                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11870                 :            : 
   11871                 :          0 :         entry = mlx5_hlist_register(priv->sh->flow_tbls, table_key.v64, &ctx);
   11872         [ #  # ]:          0 :         if (!entry) {
   11873                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11874                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11875                 :            :                                    "cannot get table");
   11876                 :          0 :                 return NULL;
   11877                 :            :         }
   11878         [ #  # ]:          0 :         DRV_LOG(DEBUG, "table_level %u table_id %u "
   11879                 :            :                 "tunnel %u group %u registered.",
   11880                 :            :                 table_level, table_id,
   11881                 :            :                 tunnel ? tunnel->tunnel_id : 0, group_id);
   11882                 :            :         tbl_data = container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11883                 :          0 :         return &tbl_data->tbl;
   11884                 :            : }
   11885                 :            : 
   11886                 :            : void
   11887                 :          0 : flow_dv_tbl_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11888                 :            : {
   11889                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11890                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11891                 :            :                     container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11892                 :            : 
   11893                 :            :         MLX5_ASSERT(entry && sh);
   11894         [ #  # ]:          0 :         if (tbl_data->jump.action)
   11895                 :            :                 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action);
   11896         [ #  # ]:          0 :         if (tbl_data->tbl.obj)
   11897                 :            :                 mlx5_flow_os_destroy_flow_tbl(tbl_data->tbl.obj);
   11898         [ #  # ]:          0 :         if (tbl_data->tunnel_offload && tbl_data->external) {
   11899                 :            :                 struct mlx5_list_entry *he;
   11900                 :            :                 struct mlx5_hlist *tunnel_grp_hash;
   11901                 :          0 :                 struct mlx5_flow_tunnel_hub *thub = sh->tunnel_hub;
   11902                 :          0 :                 union tunnel_tbl_key tunnel_key = {
   11903                 :          0 :                         .tunnel_id = tbl_data->tunnel ?
   11904         [ #  # ]:          0 :                                         tbl_data->tunnel->tunnel_id : 0,
   11905                 :          0 :                         .group = tbl_data->group_id
   11906                 :            :                 };
   11907                 :          0 :                 uint32_t table_level = tbl_data->level;
   11908                 :          0 :                 struct mlx5_flow_cb_ctx ctx = {
   11909                 :            :                         .data = (void *)&tunnel_key.val,
   11910                 :            :                 };
   11911                 :            : 
   11912                 :            :                 tunnel_grp_hash = tbl_data->tunnel ?
   11913         [ #  # ]:          0 :                                         tbl_data->tunnel->groups :
   11914                 :            :                                         thub->groups;
   11915                 :          0 :                 he = mlx5_hlist_lookup(tunnel_grp_hash, tunnel_key.val, &ctx);
   11916         [ #  # ]:          0 :                 if (he)
   11917                 :          0 :                         mlx5_hlist_unregister(tunnel_grp_hash, he);
   11918         [ #  # ]:          0 :                 DRV_LOG(DEBUG,
   11919                 :            :                         "table_level %u id %u tunnel %u group %u released.",
   11920                 :            :                         table_level,
   11921                 :            :                         tbl_data->id,
   11922                 :            :                         tbl_data->tunnel ?
   11923                 :            :                         tbl_data->tunnel->tunnel_id : 0,
   11924                 :            :                         tbl_data->group_id);
   11925                 :            :         }
   11926         [ #  # ]:          0 :         if (tbl_data->matchers)
   11927                 :          0 :                 mlx5_list_destroy(tbl_data->matchers);
   11928                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx);
   11929                 :          0 : }
   11930                 :            : 
   11931                 :            : /**
   11932                 :            :  * Release a flow table.
   11933                 :            :  *
   11934                 :            :  * @param[in] sh
   11935                 :            :  *   Pointer to device shared structure.
   11936                 :            :  * @param[in] tbl
   11937                 :            :  *   Table resource to be released.
   11938                 :            :  *
   11939                 :            :  * @return
   11940                 :            :  *   Returns 0 if table was released, else return 1;
   11941                 :            :  */
   11942                 :            : int
   11943                 :          0 : flow_dv_tbl_resource_release(struct mlx5_dev_ctx_shared *sh,
   11944                 :            :                              struct mlx5_flow_tbl_resource *tbl)
   11945                 :            : {
   11946                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11947                 :          0 :                 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
   11948                 :            : 
   11949         [ #  # ]:          0 :         if (!tbl)
   11950                 :            :                 return 0;
   11951                 :          0 :         return mlx5_hlist_unregister(sh->flow_tbls, &tbl_data->entry);
   11952                 :            : }
   11953                 :            : 
   11954                 :            : int
   11955                 :          0 : flow_matcher_match_cb(void *tool_ctx __rte_unused,
   11956                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
   11957                 :            : {
   11958                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11959                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11960                 :            :         struct mlx5_flow_dv_matcher *cur = container_of(entry, typeof(*cur),
   11961                 :            :                                                         entry);
   11962                 :            : 
   11963                 :          0 :         return cur->crc != ref->crc ||
   11964         [ #  # ]:          0 :                cur->priority != ref->priority ||
   11965                 :          0 :                memcmp((const void *)cur->mask.buf,
   11966         [ #  # ]:          0 :                       (const void *)ref->mask.buf, ref->mask.size);
   11967                 :            : }
   11968                 :            : 
   11969                 :            : struct mlx5_list_entry *
   11970                 :          0 : flow_matcher_create_cb(void *tool_ctx, void *cb_ctx)
   11971                 :            : {
   11972                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11973                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11974                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11975                 :            :         struct mlx5_flow_dv_matcher *resource;
   11976                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   11977                 :            :         const struct rte_flow_item *items;
   11978                 :            : #endif
   11979                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   11980                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   11981                 :          0 :                 .match_mask = (void *)&ref->mask,
   11982                 :            :         };
   11983                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   11984                 :            :         int ret;
   11985                 :            : 
   11986                 :          0 :         resource = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*resource), 0,
   11987                 :            :                                SOCKET_ID_ANY);
   11988         [ #  # ]:          0 :         if (!resource) {
   11989                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11990                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11991                 :            :                                    "cannot create matcher");
   11992                 :          0 :                 return NULL;
   11993                 :            :         }
   11994                 :          0 :         *resource = *ref;
   11995         [ #  # ]:          0 :         if (sh->config.dv_flow_en != 2) {
   11996                 :          0 :                 tbl = container_of(ref->tbl, typeof(*tbl), tbl);
   11997                 :          0 :                 dv_attr.match_criteria_enable =
   11998         [ #  # ]:          0 :                         flow_dv_matcher_enable(resource->mask.buf);
   11999                 :            :                 __flow_dv_adjust_buf_size(&ref->mask.size,
   12000                 :            :                                         dv_attr.match_criteria_enable);
   12001                 :          0 :                 dv_attr.priority = ref->priority;
   12002         [ #  # ]:          0 :                 if (tbl->is_egress)
   12003                 :          0 :                         dv_attr.flags |= IBV_FLOW_ATTR_FLAGS_EGRESS;
   12004                 :          0 :                 ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   12005                 :            :                                                 tbl->tbl.obj,
   12006                 :            :                                                 &resource->matcher_object);
   12007                 :            :                 if (ret) {
   12008                 :          0 :                         mlx5_free(resource);
   12009                 :          0 :                         rte_flow_error_set(ctx->error, ENOMEM,
   12010                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12011                 :            :                                         "cannot create matcher");
   12012                 :          0 :                         return NULL;
   12013                 :            :                 }
   12014                 :            :         } else {
   12015                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   12016                 :          0 :                 items = *((const struct rte_flow_item **)(ctx->data2));
   12017                 :          0 :                 resource->matcher_object = mlx5dr_bwc_matcher_create
   12018                 :          0 :                                 (resource->group->tbl, resource->priority, items);
   12019         [ #  # ]:          0 :                 if (!resource->matcher_object) {
   12020                 :          0 :                         mlx5_free(resource);
   12021                 :          0 :                         return NULL;
   12022                 :            :                 }
   12023                 :            : #else
   12024                 :            :                 mlx5_free(resource);
   12025                 :            :                 return NULL;
   12026                 :            : #endif
   12027                 :            :         }
   12028                 :          0 :         return &resource->entry;
   12029                 :            : }
   12030                 :            : 
   12031                 :            : /**
   12032                 :            :  * Register the flow matcher.
   12033                 :            :  *
   12034                 :            :  * @param[in, out] dev
   12035                 :            :  *   Pointer to rte_eth_dev structure.
   12036                 :            :  * @param[in, out] matcher
   12037                 :            :  *   Pointer to flow matcher.
   12038                 :            :  * @param[in, out] key
   12039                 :            :  *   Pointer to flow table key.
   12040                 :            :  * @parm[in, out] dev_flow
   12041                 :            :  *   Pointer to the dev_flow.
   12042                 :            :  * @param[out] error
   12043                 :            :  *   pointer to error structure.
   12044                 :            :  *
   12045                 :            :  * @return
   12046                 :            :  *   0 on success otherwise -errno and errno is set.
   12047                 :            :  */
   12048                 :            : static int
   12049                 :          0 : flow_dv_matcher_register(struct rte_eth_dev *dev,
   12050                 :            :                          struct mlx5_flow_dv_matcher *ref,
   12051                 :            :                          union mlx5_flow_tbl_key *key,
   12052                 :            :                          struct mlx5_flow *dev_flow,
   12053                 :            :                          const struct mlx5_flow_tunnel *tunnel,
   12054                 :            :                          uint32_t group_id,
   12055                 :            :                          struct rte_flow_error *error)
   12056                 :            : {
   12057                 :            :         struct mlx5_list_entry *entry;
   12058                 :            :         struct mlx5_flow_dv_matcher *resource;
   12059                 :            :         struct mlx5_flow_tbl_resource *tbl;
   12060                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   12061                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12062                 :            :                 .error = error,
   12063                 :            :                 .data = ref,
   12064                 :            :         };
   12065                 :            :         /**
   12066                 :            :          * tunnel offload API requires this registration for cases when
   12067                 :            :          * tunnel match rule was inserted before tunnel set rule.
   12068                 :            :          */
   12069                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, key->level,
   12070                 :          0 :                                        key->is_egress, key->is_fdb,
   12071                 :          0 :                                        dev_flow->external, tunnel,
   12072                 :          0 :                                        group_id, 0, key->id, error);
   12073         [ #  # ]:          0 :         if (!tbl)
   12074                 :          0 :                 return -rte_errno;      /* No need to refill the error info */
   12075                 :          0 :         tbl_data = container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
   12076                 :          0 :         ref->tbl = tbl;
   12077                 :          0 :         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   12078         [ #  # ]:          0 :         if (!entry) {
   12079                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   12080                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   12081                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12082                 :            :                                           "cannot allocate ref memory");
   12083                 :            :         }
   12084                 :            :         resource = container_of(entry, typeof(*resource), entry);
   12085                 :          0 :         dev_flow->handle->dvh.matcher = resource;
   12086                 :          0 :         return 0;
   12087                 :            : }
   12088                 :            : 
   12089                 :            : struct mlx5_list_entry *
   12090                 :          0 : flow_dv_tag_create_cb(void *tool_ctx, void *cb_ctx)
   12091                 :            : {
   12092                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12093                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12094                 :            :         struct mlx5_flow_dv_tag_resource *entry;
   12095                 :          0 :         uint32_t idx = 0;
   12096                 :            :         int ret;
   12097                 :            : 
   12098                 :          0 :         entry = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_TAG], &idx);
   12099         [ #  # ]:          0 :         if (!entry) {
   12100                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12101                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12102                 :            :                                    "cannot allocate resource memory");
   12103                 :          0 :                 return NULL;
   12104                 :            :         }
   12105                 :          0 :         entry->idx = idx;
   12106                 :          0 :         entry->tag_id = *(uint32_t *)(ctx->data);
   12107                 :            :         ret = mlx5_flow_os_create_flow_action_tag(entry->tag_id,
   12108                 :            :                                                   &entry->action);
   12109                 :            :         if (ret) {
   12110                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], idx);
   12111                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12112                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12113                 :            :                                    NULL, "cannot create action");
   12114                 :          0 :                 return NULL;
   12115                 :            :         }
   12116                 :          0 :         return &entry->entry;
   12117                 :            : }
   12118                 :            : 
   12119                 :            : int
   12120                 :          0 : flow_dv_tag_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
   12121                 :            :                      void *cb_ctx)
   12122                 :            : {
   12123                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12124                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12125                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12126                 :            : 
   12127                 :          0 :         return *(uint32_t *)(ctx->data) != tag->tag_id;
   12128                 :            : }
   12129                 :            : 
   12130                 :            : struct mlx5_list_entry *
   12131                 :          0 : flow_dv_tag_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
   12132                 :            :                      void *cb_ctx)
   12133                 :            : {
   12134                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12135                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12136                 :            :         struct mlx5_flow_dv_tag_resource *entry;
   12137                 :          0 :         uint32_t idx = 0;
   12138                 :            : 
   12139                 :          0 :         entry = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_TAG], &idx);
   12140         [ #  # ]:          0 :         if (!entry) {
   12141                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12142                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12143                 :            :                                    "cannot allocate tag resource memory");
   12144                 :          0 :                 return NULL;
   12145                 :            :         }
   12146                 :            :         memcpy(entry, oentry, sizeof(*entry));
   12147                 :          0 :         entry->idx = idx;
   12148                 :          0 :         return &entry->entry;
   12149                 :            : }
   12150                 :            : 
   12151                 :            : void
   12152                 :          0 : flow_dv_tag_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   12153                 :            : {
   12154                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12155                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12156                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12157                 :            : 
   12158                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx);
   12159                 :          0 : }
   12160                 :            : 
   12161                 :            : /**
   12162                 :            :  * Find existing tag resource or create and register a new one.
   12163                 :            :  *
   12164                 :            :  * @param dev[in, out]
   12165                 :            :  *   Pointer to rte_eth_dev structure.
   12166                 :            :  * @param[in, out] tag_be24
   12167                 :            :  *   Tag value in big endian then R-shift 8.
   12168                 :            :  * @parm[in, out] dev_flow
   12169                 :            :  *   Pointer to the dev_flow.
   12170                 :            :  * @param[out] error
   12171                 :            :  *   pointer to error structure.
   12172                 :            :  *
   12173                 :            :  * @return
   12174                 :            :  *   0 on success otherwise -errno and errno is set.
   12175                 :            :  */
   12176                 :            : static int
   12177                 :          0 : flow_dv_tag_resource_register
   12178                 :            :                         (struct rte_eth_dev *dev,
   12179                 :            :                          uint32_t tag_be24,
   12180                 :            :                          struct mlx5_flow *dev_flow,
   12181                 :            :                          struct rte_flow_error *error)
   12182                 :            : {
   12183                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12184                 :            :         struct mlx5_flow_dv_tag_resource *resource;
   12185                 :            :         struct mlx5_list_entry *entry;
   12186                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12187                 :            :                                         .error = error,
   12188                 :            :                                         .data = &tag_be24,
   12189                 :            :                                         };
   12190                 :            :         struct mlx5_hlist *tag_table;
   12191                 :            : 
   12192                 :          0 :         tag_table = flow_dv_hlist_prepare(priv->sh, &priv->sh->tag_table,
   12193                 :            :                                       "tags",
   12194                 :            :                                       MLX5_TAGS_HLIST_ARRAY_SIZE,
   12195                 :          0 :                                       false, false, priv->sh,
   12196                 :            :                                       flow_dv_tag_create_cb,
   12197                 :            :                                       flow_dv_tag_match_cb,
   12198                 :            :                                       flow_dv_tag_remove_cb,
   12199                 :            :                                       flow_dv_tag_clone_cb,
   12200                 :            :                                       flow_dv_tag_clone_free_cb,
   12201                 :            :                                       error);
   12202         [ #  # ]:          0 :         if (unlikely(!tag_table))
   12203                 :          0 :                 return -rte_errno;
   12204                 :          0 :         entry = mlx5_hlist_register(tag_table, tag_be24, &ctx);
   12205         [ #  # ]:          0 :         if (entry) {
   12206                 :            :                 resource = container_of(entry, struct mlx5_flow_dv_tag_resource,
   12207                 :            :                                         entry);
   12208                 :          0 :                 dev_flow->handle->dvh.rix_tag = resource->idx;
   12209                 :          0 :                 dev_flow->dv.tag_resource = resource;
   12210                 :          0 :                 return 0;
   12211                 :            :         }
   12212                 :          0 :         return -rte_errno;
   12213                 :            : }
   12214                 :            : 
   12215                 :            : void
   12216                 :          0 : flow_dv_tag_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   12217                 :            : {
   12218                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12219                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12220                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12221                 :            : 
   12222                 :            :         MLX5_ASSERT(tag && sh && tag->action);
   12223                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(tag->action));
   12224                 :          0 :         DRV_LOG(DEBUG, "Tag %p: removed.", (void *)tag);
   12225                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx);
   12226                 :          0 : }
   12227                 :            : 
   12228                 :            : /**
   12229                 :            :  * Release the tag.
   12230                 :            :  *
   12231                 :            :  * @param dev
   12232                 :            :  *   Pointer to Ethernet device.
   12233                 :            :  * @param tag_idx
   12234                 :            :  *   Tag index.
   12235                 :            :  *
   12236                 :            :  * @return
   12237                 :            :  *   1 while a reference on it exists, 0 when freed.
   12238                 :            :  */
   12239                 :            : static int
   12240                 :          0 : flow_dv_tag_release(struct rte_eth_dev *dev,
   12241                 :            :                     uint32_t tag_idx)
   12242                 :            : {
   12243                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12244                 :            :         struct mlx5_flow_dv_tag_resource *tag;
   12245                 :            : 
   12246                 :          0 :         tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG], tag_idx);
   12247         [ #  # ]:          0 :         if (!tag)
   12248                 :            :                 return 0;
   12249                 :          0 :         DRV_LOG(DEBUG, "port %u tag %p: refcnt %d--",
   12250                 :            :                 dev->data->port_id, (void *)tag, tag->entry.ref_cnt);
   12251                 :          0 :         return mlx5_hlist_unregister(priv->sh->tag_table, &tag->entry);
   12252                 :            : }
   12253                 :            : 
   12254                 :            : /**
   12255                 :            :  * Translate action PORT_ID / REPRESENTED_PORT to vport.
   12256                 :            :  *
   12257                 :            :  * @param[in] dev
   12258                 :            :  *   Pointer to rte_eth_dev structure.
   12259                 :            :  * @param[in] action
   12260                 :            :  *   Pointer to action PORT_ID / REPRESENTED_PORT.
   12261                 :            :  * @param[out] dst_port_id
   12262                 :            :  *   The target port ID.
   12263                 :            :  * @param[out] error
   12264                 :            :  *   Pointer to the error structure.
   12265                 :            :  *
   12266                 :            :  * @return
   12267                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   12268                 :            :  */
   12269                 :            : static int
   12270                 :          0 : flow_dv_translate_action_port_id(struct rte_eth_dev *dev,
   12271                 :            :                                  const struct rte_flow_action *action,
   12272                 :            :                                  uint32_t *dst_port_id,
   12273                 :            :                                  struct rte_flow_error *error)
   12274                 :            : {
   12275                 :            :         uint32_t port;
   12276                 :            :         struct mlx5_priv *priv;
   12277                 :            : 
   12278      [ #  #  # ]:          0 :         switch (action->type) {
   12279                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID: {
   12280                 :            :                 const struct rte_flow_action_port_id *conf;
   12281                 :            : 
   12282                 :          0 :                 conf = (const struct rte_flow_action_port_id *)action->conf;
   12283         [ #  # ]:          0 :                 port = conf->original ? dev->data->port_id : conf->id;
   12284                 :            :                 break;
   12285                 :            :         }
   12286                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: {
   12287                 :            :                 const struct rte_flow_action_ethdev *ethdev;
   12288                 :            : 
   12289                 :          0 :                 ethdev = (const struct rte_flow_action_ethdev *)action->conf;
   12290                 :          0 :                 port = ethdev->port_id;
   12291                 :          0 :                 break;
   12292                 :            :         }
   12293                 :          0 :         default:
   12294                 :            :                 MLX5_ASSERT(false);
   12295                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12296                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
   12297                 :            :                                           "unknown E-Switch action");
   12298                 :            :         }
   12299                 :            : 
   12300                 :          0 :         priv = mlx5_port_to_eswitch_info(port, false);
   12301         [ #  # ]:          0 :         if (!priv)
   12302                 :          0 :                 return rte_flow_error_set(error, -rte_errno,
   12303                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   12304                 :            :                                           NULL,
   12305                 :            :                                           "No eswitch info was found for port");
   12306                 :            : #ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT
   12307                 :            :         /*
   12308                 :            :          * This parameter is transferred to
   12309                 :            :          * mlx5dv_dr_action_create_dest_ib_port().
   12310                 :            :          */
   12311                 :          0 :         *dst_port_id = priv->dev_port;
   12312                 :            : #else
   12313                 :            :         /*
   12314                 :            :          * Legacy mode, no LAG configurations is supported.
   12315                 :            :          * This parameter is transferred to
   12316                 :            :          * mlx5dv_dr_action_create_dest_vport().
   12317                 :            :          */
   12318                 :            :         *dst_port_id = priv->vport_id;
   12319                 :            : #endif
   12320                 :          0 :         return 0;
   12321                 :            : }
   12322                 :            : 
   12323                 :            : /**
   12324                 :            :  * Create a counter with aging configuration.
   12325                 :            :  *
   12326                 :            :  * @param[in] dev
   12327                 :            :  *   Pointer to rte_eth_dev structure.
   12328                 :            :  * @param[in] dev_flow
   12329                 :            :  *   Pointer to the mlx5_flow.
   12330                 :            :  * @param[out] count
   12331                 :            :  *   Pointer to the counter action configuration.
   12332                 :            :  * @param[in] age
   12333                 :            :  *   Pointer to the aging action configuration.
   12334                 :            :  *
   12335                 :            :  * @return
   12336                 :            :  *   Index to flow counter on success, 0 otherwise.
   12337                 :            :  */
   12338                 :            : static uint32_t
   12339                 :          0 : flow_dv_translate_create_counter(struct rte_eth_dev *dev,
   12340                 :            :                                 struct mlx5_flow *dev_flow,
   12341                 :            :                                 const struct rte_flow_action_count *count
   12342                 :            :                                         __rte_unused,
   12343                 :            :                                 const struct rte_flow_action_age *age)
   12344                 :            : {
   12345                 :            :         uint32_t counter;
   12346                 :            :         struct mlx5_age_param *age_param;
   12347                 :            : 
   12348                 :          0 :         counter = flow_dv_counter_alloc(dev, !!age);
   12349         [ #  # ]:          0 :         if (!counter || age == NULL)
   12350                 :            :                 return counter;
   12351                 :            :         age_param = flow_dv_counter_idx_get_age(dev, counter);
   12352         [ #  # ]:          0 :         age_param->context = age->context ? age->context :
   12353                 :          0 :                 (void *)(uintptr_t)(dev_flow->flow_idx);
   12354                 :          0 :         age_param->timeout = age->timeout;
   12355                 :          0 :         age_param->port_id = dev->data->port_id;
   12356                 :          0 :         rte_atomic_store_explicit(&age_param->sec_since_last_hit, 0, rte_memory_order_relaxed);
   12357                 :          0 :         rte_atomic_store_explicit(&age_param->state, AGE_CANDIDATE, rte_memory_order_relaxed);
   12358                 :          0 :         return counter;
   12359                 :            : }
   12360                 :            : 
   12361                 :            : /**
   12362                 :            :  * Add Tx queue matcher
   12363                 :            :  *
   12364                 :            :  * @param[in] dev
   12365                 :            :  *   Pointer to rte_eth_dev structure.
   12366                 :            :  * @param[in, out] key
   12367                 :            :  *   Flow matcher value.
   12368                 :            :  * @param[in] item
   12369                 :            :  *   Flow pattern to translate.
   12370                 :            :  * @param[in] key_type
   12371                 :            :  *   Set flow matcher mask or value.
   12372                 :            :  *
   12373                 :            :  * @return
   12374                 :            :  *   0 on success otherwise -errno and errno is set.
   12375                 :            :  */
   12376                 :            : static int
   12377                 :          0 : flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev, void *key,
   12378                 :            :                                 const struct rte_flow_item *item, uint32_t key_type)
   12379                 :            : {
   12380                 :            :         const struct rte_flow_item_tx_queue *queue_m;
   12381                 :            :         const struct rte_flow_item_tx_queue *queue_v;
   12382                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   12383                 :            :         uint32_t tx_queue;
   12384                 :            :         uint32_t sqn = 0;
   12385                 :            :         int ret;
   12386                 :            : 
   12387   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, queue_v, queue_m, &rte_flow_item_tx_queue_mask);
             #  #  #  # ]
   12388         [ #  # ]:          0 :         if (!queue_m || !queue_v)
   12389                 :            :                 return -EINVAL;
   12390         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_V) {
   12391                 :          0 :                 tx_queue = queue_v->tx_queue;
   12392         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_V)
   12393                 :          0 :                         tx_queue &= queue_m->tx_queue;
   12394         [ #  # ]:          0 :                 ret = flow_hw_get_sqn(dev, tx_queue, &sqn);
   12395         [ #  # ]:          0 :                 if (unlikely(ret))
   12396                 :          0 :                         return -ret;
   12397                 :            :         } else {
   12398                 :            :                 /* Due to tx_queue to sqn converting, only fully masked value support. */
   12399         [ #  # ]:          0 :                 if (queue_m->tx_queue != rte_flow_item_tx_queue_mask.tx_queue)
   12400                 :            :                         return -EINVAL;
   12401                 :            :                 sqn = UINT32_MAX;
   12402                 :            :         }
   12403         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_sqn, sqn);
   12404                 :          0 :         return 0;
   12405                 :            : }
   12406                 :            : 
   12407                 :            : /**
   12408                 :            :  * Add SQ matcher
   12409                 :            :  *
   12410                 :            :  * @param[in, out] matcher
   12411                 :            :  *   Flow matcher.
   12412                 :            :  * @param[in, out] key
   12413                 :            :  *   Flow matcher value.
   12414                 :            :  * @param[in] item
   12415                 :            :  *   Flow pattern to translate.
   12416                 :            :  * @param[in] key_type
   12417                 :            :  *   Set flow matcher mask or value.
   12418                 :            :  */
   12419                 :            : static void
   12420                 :          0 : flow_dv_translate_item_sq(void *key,
   12421                 :            :                           const struct rte_flow_item *item,
   12422                 :            :                           uint32_t key_type)
   12423                 :            : {
   12424                 :            :         const struct mlx5_rte_flow_item_sq *queue_m;
   12425                 :            :         const struct mlx5_rte_flow_item_sq *queue_v;
   12426                 :          0 :         const struct mlx5_rte_flow_item_sq queue_mask = {
   12427                 :            :                 .queue = UINT32_MAX,
   12428                 :            :         };
   12429                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   12430                 :            :         uint32_t queue;
   12431                 :            : 
   12432   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, queue_v, queue_m, &queue_mask);
             #  #  #  # ]
   12433         [ #  # ]:          0 :         if (!queue_m || !queue_v)
   12434                 :          0 :                 return;
   12435         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_V) {
   12436                 :          0 :                 queue = queue_v->queue;
   12437         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_V)
   12438                 :          0 :                         queue &= queue_m->queue;
   12439                 :            :         } else {
   12440                 :          0 :                 queue = queue_m->queue;
   12441                 :            :         }
   12442         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_sqn, queue);
   12443                 :            : }
   12444                 :            : 
   12445                 :            : /**
   12446                 :            :  * Set the hash fields according to the @p flow information.
   12447                 :            :  *
   12448                 :            :  * @param[in] item_flags
   12449                 :            :  *   The match pattern item flags.
   12450                 :            :  * @param[in] rss_desc
   12451                 :            :  *   Pointer to the mlx5_flow_rss_desc.
   12452                 :            :  * @param[out] hash_fields
   12453                 :            :  *   Pointer to the RSS hash fields.
   12454                 :            :  */
   12455                 :            : void
   12456                 :          0 : flow_dv_hashfields_set(uint64_t item_flags,
   12457                 :            :                        struct mlx5_flow_rss_desc *rss_desc,
   12458                 :            :                        uint64_t *hash_fields)
   12459                 :            : {
   12460                 :            :         uint64_t items = item_flags;
   12461                 :            :         uint64_t fields = 0;
   12462                 :            :         int rss_inner = 0;
   12463         [ #  # ]:          0 :         uint64_t rss_types = rte_eth_rss_hf_refine(rss_desc->types);
   12464                 :            : 
   12465                 :            :         *hash_fields = 0;
   12466                 :            : #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
   12467         [ #  # ]:          0 :         if (rss_desc->level >= 2)
   12468                 :            :                 rss_inner = 1;
   12469                 :            : #endif
   12470   [ #  #  #  # ]:          0 :         if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV4)) ||
   12471         [ #  # ]:          0 :             (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV4))) {
   12472         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV4_LAYER_TYPES) {
   12473         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   12474                 :            :                                 fields |= IBV_RX_HASH_SRC_IPV4;
   12475         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   12476                 :            :                                 fields |= IBV_RX_HASH_DST_IPV4;
   12477                 :            :                         else
   12478                 :            :                                 fields |= MLX5_IPV4_IBV_RX_HASH;
   12479                 :            :                 }
   12480   [ #  #  #  #  :          0 :         } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV6)) ||
                   #  # ]
   12481         [ #  # ]:          0 :                    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV6))) {
   12482         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV6_LAYER_TYPES) {
   12483         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   12484                 :            :                                 fields |= IBV_RX_HASH_SRC_IPV6;
   12485         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   12486                 :            :                                 fields |= IBV_RX_HASH_DST_IPV6;
   12487                 :            :                         else
   12488                 :            :                                 fields |= MLX5_IPV6_IBV_RX_HASH;
   12489                 :            :                 }
   12490                 :            :         }
   12491         [ #  # ]:          0 :         if (items & MLX5_FLOW_ITEM_ESP) {
   12492         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_ESP)
   12493                 :          0 :                         fields |= IBV_RX_HASH_IPSEC_SPI;
   12494                 :            :         }
   12495         [ #  # ]:          0 :         if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
   12496                 :          0 :                 *hash_fields = fields;
   12497                 :            :                 /*
   12498                 :            :                  * There is no match between the RSS types and the
   12499                 :            :                  * L3 protocol (IPv4/IPv6) defined in the flow rule.
   12500                 :            :                  */
   12501                 :          0 :                 return;
   12502                 :            :         }
   12503   [ #  #  #  #  :          0 :         if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
                   #  # ]
   12504         [ #  # ]:          0 :             (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP))) {
   12505         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_UDP) {
   12506         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   12507                 :          0 :                                 fields |= IBV_RX_HASH_SRC_PORT_UDP;
   12508         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   12509                 :          0 :                                 fields |= IBV_RX_HASH_DST_PORT_UDP;
   12510                 :            :                         else
   12511                 :          0 :                                 fields |= MLX5_UDP_IBV_RX_HASH;
   12512                 :            :                 }
   12513   [ #  #  #  #  :          0 :         } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_TCP)) ||
                   #  # ]
   12514         [ #  # ]:          0 :                    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_TCP))) {
   12515         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_TCP) {
   12516         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   12517                 :          0 :                                 fields |= IBV_RX_HASH_SRC_PORT_TCP;
   12518         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   12519                 :          0 :                                 fields |= IBV_RX_HASH_DST_PORT_TCP;
   12520                 :            :                         else
   12521                 :          0 :                                 fields |= MLX5_TCP_IBV_RX_HASH;
   12522                 :            :                 }
   12523                 :            :         }
   12524         [ #  # ]:          0 :         if (rss_inner)
   12525                 :          0 :                 fields |= IBV_RX_HASH_INNER;
   12526                 :          0 :         *hash_fields = fields;
   12527                 :            : }
   12528                 :            : 
   12529                 :            : /**
   12530                 :            :  * Prepare an Rx Hash queue.
   12531                 :            :  *
   12532                 :            :  * @param dev
   12533                 :            :  *   Pointer to Ethernet device.
   12534                 :            :  * @param[in] dev_flow
   12535                 :            :  *   Pointer to the mlx5_flow.
   12536                 :            :  * @param[in] rss_desc
   12537                 :            :  *   Pointer to the mlx5_flow_rss_desc.
   12538                 :            :  * @param[out] hrxq_idx
   12539                 :            :  *   Hash Rx queue index.
   12540                 :            :  *
   12541                 :            :  * @return
   12542                 :            :  *   The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.
   12543                 :            :  */
   12544                 :            : static struct mlx5_hrxq *
   12545                 :          0 : flow_dv_hrxq_prepare(struct rte_eth_dev *dev,
   12546                 :            :                      struct mlx5_flow *dev_flow,
   12547                 :            :                      struct mlx5_flow_rss_desc *rss_desc,
   12548                 :            :                      uint32_t *hrxq_idx)
   12549                 :            : {
   12550                 :          0 :         struct mlx5_flow_handle *dh = dev_flow->handle;
   12551                 :          0 :         uint32_t shared_rss = rss_desc->shared_rss;
   12552                 :            :         struct mlx5_hrxq *hrxq;
   12553                 :            : 
   12554                 :            :         MLX5_ASSERT(rss_desc->queue_num);
   12555                 :          0 :         rss_desc->symmetric_hash_function = dev_flow->symmetric_hash_function;
   12556                 :          0 :         rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN;
   12557                 :          0 :         rss_desc->hash_fields = dev_flow->hash_fields;
   12558                 :          0 :         rss_desc->tunnel = !!(dh->layers & MLX5_FLOW_LAYER_TUNNEL);
   12559                 :          0 :         rss_desc->shared_rss = 0;
   12560         [ #  # ]:          0 :         if (rss_desc->hash_fields == 0)
   12561                 :          0 :                 rss_desc->queue_num = 1;
   12562                 :          0 :         hrxq = mlx5_hrxq_get(dev, rss_desc);
   12563         [ #  # ]:          0 :         *hrxq_idx = hrxq ? hrxq->idx : 0;
   12564                 :          0 :         rss_desc->shared_rss = shared_rss;
   12565                 :          0 :         return hrxq;
   12566                 :            : }
   12567                 :            : 
   12568                 :            : /**
   12569                 :            :  * Release sample sub action resource.
   12570                 :            :  *
   12571                 :            :  * @param[in, out] dev
   12572                 :            :  *   Pointer to rte_eth_dev structure.
   12573                 :            :  * @param[in] act_res
   12574                 :            :  *   Pointer to sample sub action resource.
   12575                 :            :  */
   12576                 :            : static void
   12577                 :          0 : flow_dv_sample_sub_actions_release(struct rte_eth_dev *dev,
   12578                 :            :                                    struct mlx5_flow_sub_actions_idx *act_res)
   12579                 :            : {
   12580         [ #  # ]:          0 :         if (act_res->rix_hrxq) {
   12581                 :          0 :                 mlx5_hrxq_release(dev, act_res->rix_hrxq);
   12582                 :          0 :                 act_res->rix_hrxq = 0;
   12583                 :            :         }
   12584         [ #  # ]:          0 :         if (act_res->rix_encap_decap) {
   12585                 :          0 :                 flow_encap_decap_resource_release(dev,
   12586                 :            :                                                      act_res->rix_encap_decap);
   12587                 :          0 :                 act_res->rix_encap_decap = 0;
   12588                 :            :         }
   12589         [ #  # ]:          0 :         if (act_res->rix_port_id_action) {
   12590                 :          0 :                 flow_dv_port_id_action_resource_release(dev,
   12591                 :            :                                                 act_res->rix_port_id_action);
   12592                 :          0 :                 act_res->rix_port_id_action = 0;
   12593                 :            :         }
   12594         [ #  # ]:          0 :         if (act_res->rix_tag) {
   12595                 :          0 :                 flow_dv_tag_release(dev, act_res->rix_tag);
   12596                 :          0 :                 act_res->rix_tag = 0;
   12597                 :            :         }
   12598         [ #  # ]:          0 :         if (act_res->rix_jump) {
   12599                 :          0 :                 flow_dv_jump_tbl_resource_release(dev, act_res->rix_jump);
   12600                 :          0 :                 act_res->rix_jump = 0;
   12601                 :            :         }
   12602                 :          0 : }
   12603                 :            : 
   12604                 :            : int
   12605                 :          0 : flow_dv_sample_match_cb(void *tool_ctx __rte_unused,
   12606                 :            :                         struct mlx5_list_entry *entry, void *cb_ctx)
   12607                 :            : {
   12608                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12609                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12610                 :          0 :         struct mlx5_flow_dv_sample_resource *ctx_resource = ctx->data;
   12611                 :            :         struct mlx5_flow_dv_sample_resource *resource = container_of(entry,
   12612                 :            :                                                               typeof(*resource),
   12613                 :            :                                                               entry);
   12614                 :            : 
   12615         [ #  # ]:          0 :         if (ctx_resource->ratio == resource->ratio &&
   12616         [ #  # ]:          0 :             ctx_resource->ft_type == resource->ft_type &&
   12617         [ #  # ]:          0 :             ctx_resource->ft_id == resource->ft_id &&
   12618         [ #  # ]:          0 :             ctx_resource->set_action == resource->set_action &&
   12619                 :          0 :             !memcmp((void *)&ctx_resource->sample_act,
   12620         [ #  # ]:          0 :                     (void *)&resource->sample_act,
   12621                 :            :                     sizeof(struct mlx5_flow_sub_actions_list))) {
   12622                 :            :                 /*
   12623                 :            :                  * Existing sample action should release the prepared
   12624                 :            :                  * sub-actions reference counter.
   12625                 :            :                  */
   12626                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12627                 :            :                                                    &ctx_resource->sample_idx);
   12628                 :          0 :                 return 0;
   12629                 :            :         }
   12630                 :            :         return 1;
   12631                 :            : }
   12632                 :            : 
   12633                 :            : struct mlx5_list_entry *
   12634                 :          0 : flow_dv_sample_create_cb(void *tool_ctx __rte_unused, void *cb_ctx)
   12635                 :            : {
   12636                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12637                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12638                 :          0 :         struct mlx5_flow_dv_sample_resource *ctx_resource = ctx->data;
   12639                 :          0 :         void **sample_dv_actions = ctx_resource->sub_actions;
   12640                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12641                 :            :         struct mlx5dv_dr_flow_sampler_attr sampler_attr;
   12642                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12643                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12644                 :            :         struct mlx5_flow_tbl_resource *tbl;
   12645                 :          0 :         uint32_t idx = 0;
   12646                 :            :         const uint32_t next_ft_step = 1;
   12647                 :          0 :         uint32_t next_ft_id = ctx_resource->ft_id + next_ft_step;
   12648                 :            :         uint8_t is_egress = 0;
   12649                 :            :         uint8_t is_transfer = 0;
   12650                 :          0 :         struct rte_flow_error *error = ctx->error;
   12651                 :            : 
   12652                 :            :         /* Register new sample resource. */
   12653                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);
   12654         [ #  # ]:          0 :         if (!resource) {
   12655                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12656                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12657                 :            :                                           NULL,
   12658                 :            :                                           "cannot allocate resource memory");
   12659                 :          0 :                 return NULL;
   12660                 :            :         }
   12661                 :          0 :         *resource = *ctx_resource;
   12662                 :            :         /* Create normal path table level */
   12663         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
   12664                 :            :                 is_transfer = 1;
   12665         [ #  # ]:          0 :         else if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX)
   12666                 :            :                 is_egress = 1;
   12667                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, next_ft_id,
   12668                 :            :                                         is_egress, is_transfer,
   12669                 :            :                                         true, NULL, 0, 0, 0, error);
   12670         [ #  # ]:          0 :         if (!tbl) {
   12671                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12672                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12673                 :            :                                           NULL,
   12674                 :            :                                           "fail to create normal path table "
   12675                 :            :                                           "for sample");
   12676                 :          0 :                 goto error;
   12677                 :            :         }
   12678                 :          0 :         resource->normal_path_tbl = tbl;
   12679         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
   12680         [ #  # ]:          0 :                 if (!sh->default_miss_action) {
   12681                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   12682                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12683                 :            :                                                 NULL,
   12684                 :            :                                                 "default miss action was not "
   12685                 :            :                                                 "created");
   12686                 :          0 :                         goto error;
   12687                 :            :                 }
   12688                 :          0 :                 sample_dv_actions[ctx_resource->sample_act.actions_num++] =
   12689                 :            :                                                 sh->default_miss_action;
   12690                 :            :         }
   12691                 :            :         /* Create a DR sample action */
   12692                 :          0 :         sampler_attr.sample_ratio = resource->ratio;
   12693                 :          0 :         sampler_attr.default_next_table = tbl->obj;
   12694                 :          0 :         sampler_attr.num_sample_actions = ctx_resource->sample_act.actions_num;
   12695                 :          0 :         sampler_attr.sample_actions = (struct mlx5dv_dr_action **)
   12696                 :            :                                                         &sample_dv_actions[0];
   12697                 :          0 :         sampler_attr.action = resource->set_action;
   12698                 :            :         if (mlx5_os_flow_dr_create_flow_action_sampler
   12699                 :            :                         (&sampler_attr, &resource->verbs_action)) {
   12700                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12701                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12702                 :            :                                         NULL, "cannot create sample action");
   12703                 :          0 :                 goto error;
   12704                 :            :         }
   12705                 :          0 :         resource->idx = idx;
   12706                 :          0 :         resource->dev = dev;
   12707                 :          0 :         return &resource->entry;
   12708                 :          0 : error:
   12709         [ #  # ]:          0 :         if (resource->ft_type != MLX5DV_FLOW_TABLE_TYPE_FDB)
   12710                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12711                 :            :                                                    &resource->sample_idx);
   12712         [ #  # ]:          0 :         if (resource->normal_path_tbl)
   12713                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   12714                 :            :                                 resource->normal_path_tbl);
   12715                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE], idx);
   12716                 :          0 :         return NULL;
   12717                 :            : 
   12718                 :            : }
   12719                 :            : 
   12720                 :            : struct mlx5_list_entry *
   12721                 :          0 : flow_dv_sample_clone_cb(void *tool_ctx __rte_unused,
   12722                 :            :                          struct mlx5_list_entry *entry __rte_unused,
   12723                 :            :                          void *cb_ctx)
   12724                 :            : {
   12725                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12726                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12727                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12728                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12729                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12730                 :          0 :         uint32_t idx = 0;
   12731                 :            : 
   12732                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);
   12733         [ #  # ]:          0 :         if (!resource) {
   12734                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12735                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12736                 :            :                                           NULL,
   12737                 :            :                                           "cannot allocate resource memory");
   12738                 :          0 :                 return NULL;
   12739                 :            :         }
   12740                 :            :         memcpy(resource, entry, sizeof(*resource));
   12741                 :          0 :         resource->idx = idx;
   12742                 :          0 :         resource->dev = dev;
   12743                 :          0 :         return &resource->entry;
   12744                 :            : }
   12745                 :            : 
   12746                 :            : void
   12747                 :          0 : flow_dv_sample_clone_free_cb(void *tool_ctx __rte_unused,
   12748                 :            :                              struct mlx5_list_entry *entry)
   12749                 :            : {
   12750                 :            :         struct mlx5_flow_dv_sample_resource *resource =
   12751                 :            :                                   container_of(entry, typeof(*resource), entry);
   12752                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   12753                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12754                 :            : 
   12755                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], resource->idx);
   12756                 :          0 : }
   12757                 :            : 
   12758                 :            : /**
   12759                 :            :  * Find existing sample resource or create and register a new one.
   12760                 :            :  *
   12761                 :            :  * @param[in, out] dev
   12762                 :            :  *   Pointer to rte_eth_dev structure.
   12763                 :            :  * @param[in] ref
   12764                 :            :  *   Pointer to sample resource reference.
   12765                 :            :  * @parm[in, out] dev_flow
   12766                 :            :  *   Pointer to the dev_flow.
   12767                 :            :  * @param[out] error
   12768                 :            :  *   pointer to error structure.
   12769                 :            :  *
   12770                 :            :  * @return
   12771                 :            :  *   0 on success otherwise -errno and errno is set.
   12772                 :            :  */
   12773                 :            : static int
   12774                 :          0 : flow_dv_sample_resource_register(struct rte_eth_dev *dev,
   12775                 :            :                          struct mlx5_flow_dv_sample_resource *ref,
   12776                 :            :                          struct mlx5_flow *dev_flow,
   12777                 :            :                          struct rte_flow_error *error)
   12778                 :            : {
   12779                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12780                 :            :         struct mlx5_list_entry *entry;
   12781                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12782                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12783                 :            :                 .dev = dev,
   12784                 :            :                 .error = error,
   12785                 :            :                 .data = ref,
   12786                 :            :         };
   12787                 :            : 
   12788                 :          0 :         entry = mlx5_list_register(priv->sh->sample_action_list, &ctx);
   12789         [ #  # ]:          0 :         if (!entry)
   12790                 :          0 :                 return -rte_errno;
   12791                 :            :         resource = container_of(entry, typeof(*resource), entry);
   12792                 :          0 :         dev_flow->handle->dvh.rix_sample = resource->idx;
   12793                 :          0 :         dev_flow->dv.sample_res = resource;
   12794                 :          0 :         return 0;
   12795                 :            : }
   12796                 :            : 
   12797                 :            : int
   12798                 :          0 : flow_dv_dest_array_match_cb(void *tool_ctx __rte_unused,
   12799                 :            :                             struct mlx5_list_entry *entry, void *cb_ctx)
   12800                 :            : {
   12801                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12802                 :          0 :         struct mlx5_flow_dv_dest_array_resource *ctx_resource = ctx->data;
   12803                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12804                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   12805                 :            :                                   container_of(entry, typeof(*resource), entry);
   12806                 :            :         uint32_t idx = 0;
   12807                 :            : 
   12808         [ #  # ]:          0 :         if (ctx_resource->num_of_dest == resource->num_of_dest &&
   12809                 :          0 :             ctx_resource->ft_type == resource->ft_type &&
   12810                 :          0 :             !memcmp((void *)resource->sample_act,
   12811                 :          0 :                     (void *)ctx_resource->sample_act,
   12812         [ #  # ]:          0 :                    (ctx_resource->num_of_dest *
   12813                 :            :                    sizeof(struct mlx5_flow_sub_actions_list)))) {
   12814                 :            :                 /*
   12815                 :            :                  * Existing sample action should release the prepared
   12816                 :            :                  * sub-actions reference counter.
   12817                 :            :                  */
   12818         [ #  # ]:          0 :                 for (idx = 0; idx < ctx_resource->num_of_dest; idx++)
   12819                 :          0 :                         flow_dv_sample_sub_actions_release(dev,
   12820                 :            :                                         &ctx_resource->sample_idx[idx]);
   12821                 :            :                 return 0;
   12822                 :            :         }
   12823                 :            :         return 1;
   12824                 :            : }
   12825                 :            : 
   12826                 :            : struct mlx5_list_entry *
   12827                 :          0 : flow_dv_dest_array_create_cb(void *tool_ctx __rte_unused, void *cb_ctx)
   12828                 :            : {
   12829                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12830                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12831                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12832                 :          0 :         struct mlx5_flow_dv_dest_array_resource *ctx_resource = ctx->data;
   12833                 :          0 :         struct mlx5dv_dr_action_dest_attr *dest_attr[MLX5_MAX_DEST_NUM] = { 0 };
   12834                 :            :         struct mlx5dv_dr_action_dest_reformat dest_reformat[MLX5_MAX_DEST_NUM];
   12835                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12836                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12837                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   12838                 :            :         struct mlx5dv_dr_domain *domain;
   12839                 :          0 :         uint32_t idx = 0, res_idx = 0;
   12840                 :          0 :         struct rte_flow_error *error = ctx->error;
   12841                 :            :         uint64_t action_flags;
   12842                 :            :         int ret;
   12843                 :            : 
   12844                 :            :         /* Register new destination array resource. */
   12845                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   12846                 :            :                                             &res_idx);
   12847         [ #  # ]:          0 :         if (!resource) {
   12848                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12849                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12850                 :            :                                           NULL,
   12851                 :            :                                           "cannot allocate resource memory");
   12852                 :          0 :                 return NULL;
   12853                 :            :         }
   12854                 :          0 :         *resource = *ctx_resource;
   12855         [ #  # ]:          0 :         if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
   12856                 :          0 :                 domain = sh->fdb_domain;
   12857         [ #  # ]:          0 :         else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
   12858                 :          0 :                 domain = sh->rx_domain;
   12859                 :            :         else
   12860                 :          0 :                 domain = sh->tx_domain;
   12861         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++) {
   12862                 :          0 :                 dest_attr[idx] = (struct mlx5dv_dr_action_dest_attr *)
   12863                 :          0 :                                  mlx5_malloc(MLX5_MEM_ZERO,
   12864                 :            :                                  sizeof(struct mlx5dv_dr_action_dest_attr),
   12865                 :            :                                  0, SOCKET_ID_ANY);
   12866         [ #  # ]:          0 :                 if (!dest_attr[idx]) {
   12867                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   12868                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12869                 :            :                                            NULL,
   12870                 :            :                                            "cannot allocate resource memory");
   12871                 :          0 :                         goto error;
   12872                 :            :                 }
   12873                 :          0 :                 dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST;
   12874                 :            :                 sample_act = &ctx_resource->sample_act[idx];
   12875                 :          0 :                 action_flags = sample_act->action_flags;
   12876   [ #  #  #  #  :          0 :                 switch (action_flags) {
                      # ]
   12877                 :          0 :                 case MLX5_FLOW_ACTION_QUEUE:
   12878                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_queue_action;
   12879                 :          0 :                         break;
   12880                 :          0 :                 case (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP):
   12881                 :          0 :                         dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT;
   12882                 :          0 :                         dest_attr[idx]->dest_reformat = &dest_reformat[idx];
   12883                 :          0 :                         dest_attr[idx]->dest_reformat->reformat =
   12884                 :          0 :                                         sample_act->dr_encap_action;
   12885                 :          0 :                         dest_attr[idx]->dest_reformat->dest =
   12886                 :          0 :                                         sample_act->dr_port_id_action;
   12887                 :          0 :                         break;
   12888                 :          0 :                 case MLX5_FLOW_ACTION_PORT_ID:
   12889                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_port_id_action;
   12890                 :          0 :                         break;
   12891                 :          0 :                 case MLX5_FLOW_ACTION_JUMP:
   12892                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_jump_action;
   12893                 :          0 :                         break;
   12894                 :          0 :                 default:
   12895                 :          0 :                         rte_flow_error_set(error, EINVAL,
   12896                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   12897                 :            :                                            NULL,
   12898                 :            :                                            "unsupported actions type");
   12899                 :          0 :                         goto error;
   12900                 :            :                 }
   12901                 :            :         }
   12902                 :            :         /* create a dest array action */
   12903                 :          0 :         ret = mlx5_os_flow_dr_create_flow_action_dest_array
   12904                 :            :                                                 (domain,
   12905                 :          0 :                                                  resource->num_of_dest,
   12906                 :            :                                                  dest_attr,
   12907                 :            :                                                  &resource->action);
   12908                 :            :         if (ret) {
   12909                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12910                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12911                 :            :                                    NULL,
   12912                 :            :                                    "cannot create destination array action");
   12913                 :          0 :                 goto error;
   12914                 :            :         }
   12915                 :          0 :         resource->idx = res_idx;
   12916                 :          0 :         resource->dev = dev;
   12917         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++)
   12918                 :          0 :                 mlx5_free(dest_attr[idx]);
   12919                 :          0 :         return &resource->entry;
   12920                 :            : error:
   12921         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++) {
   12922                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12923                 :            :                                                    &resource->sample_idx[idx]);
   12924         [ #  # ]:          0 :                 if (dest_attr[idx])
   12925                 :          0 :                         mlx5_free(dest_attr[idx]);
   12926                 :            :         }
   12927                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY], res_idx);
   12928                 :          0 :         return NULL;
   12929                 :            : }
   12930                 :            : 
   12931                 :            : struct mlx5_list_entry *
   12932                 :          0 : flow_dv_dest_array_clone_cb(void *tool_ctx __rte_unused,
   12933                 :            :                             struct mlx5_list_entry *entry __rte_unused,
   12934                 :            :                             void *cb_ctx)
   12935                 :            : {
   12936                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12937                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12938                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12939                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12940                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12941                 :          0 :         uint32_t res_idx = 0;
   12942                 :          0 :         struct rte_flow_error *error = ctx->error;
   12943                 :            : 
   12944                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   12945                 :            :                                       &res_idx);
   12946         [ #  # ]:          0 :         if (!resource) {
   12947                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12948                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12949                 :            :                                           NULL,
   12950                 :            :                                           "cannot allocate dest-array memory");
   12951                 :          0 :                 return NULL;
   12952                 :            :         }
   12953                 :            :         memcpy(resource, entry, sizeof(*resource));
   12954                 :          0 :         resource->idx = res_idx;
   12955                 :          0 :         resource->dev = dev;
   12956                 :          0 :         return &resource->entry;
   12957                 :            : }
   12958                 :            : 
   12959                 :            : void
   12960                 :          0 : flow_dv_dest_array_clone_free_cb(void *tool_ctx __rte_unused,
   12961                 :            :                                  struct mlx5_list_entry *entry)
   12962                 :            : {
   12963                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   12964                 :            :                         container_of(entry, typeof(*resource), entry);
   12965                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   12966                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12967                 :            : 
   12968                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], resource->idx);
   12969                 :          0 : }
   12970                 :            : 
   12971                 :            : /**
   12972                 :            :  * Find existing destination array resource or create and register a new one.
   12973                 :            :  *
   12974                 :            :  * @param[in, out] dev
   12975                 :            :  *   Pointer to rte_eth_dev structure.
   12976                 :            :  * @param[in] ref
   12977                 :            :  *   Pointer to destination array resource reference.
   12978                 :            :  * @parm[in, out] dev_flow
   12979                 :            :  *   Pointer to the dev_flow.
   12980                 :            :  * @param[out] error
   12981                 :            :  *   pointer to error structure.
   12982                 :            :  *
   12983                 :            :  * @return
   12984                 :            :  *   0 on success otherwise -errno and errno is set.
   12985                 :            :  */
   12986                 :            : static int
   12987                 :          0 : flow_dv_dest_array_resource_register(struct rte_eth_dev *dev,
   12988                 :            :                          struct mlx5_flow_dv_dest_array_resource *ref,
   12989                 :            :                          struct mlx5_flow *dev_flow,
   12990                 :            :                          struct rte_flow_error *error)
   12991                 :            : {
   12992                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12993                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12994                 :            :         struct mlx5_list_entry *entry;
   12995                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12996                 :            :                 .dev = dev,
   12997                 :            :                 .error = error,
   12998                 :            :                 .data = ref,
   12999                 :            :         };
   13000                 :            : 
   13001                 :          0 :         entry = mlx5_list_register(priv->sh->dest_array_list, &ctx);
   13002         [ #  # ]:          0 :         if (!entry)
   13003                 :          0 :                 return -rte_errno;
   13004                 :            :         resource = container_of(entry, typeof(*resource), entry);
   13005                 :          0 :         dev_flow->handle->dvh.rix_dest_array = resource->idx;
   13006                 :          0 :         dev_flow->dv.dest_array_res = resource;
   13007                 :          0 :         return 0;
   13008                 :            : }
   13009                 :            : 
   13010                 :            : /**
   13011                 :            :  * Convert Sample action to DV specification.
   13012                 :            :  *
   13013                 :            :  * @param[in] dev
   13014                 :            :  *   Pointer to rte_eth_dev structure.
   13015                 :            :  * @param[in] action
   13016                 :            :  *   Pointer to sample action structure.
   13017                 :            :  * @param[in, out] dev_flow
   13018                 :            :  *   Pointer to the mlx5_flow.
   13019                 :            :  * @param[in] attr
   13020                 :            :  *   Pointer to the flow attributes.
   13021                 :            :  * @param[in, out] num_of_dest
   13022                 :            :  *   Pointer to the num of destination.
   13023                 :            :  * @param[in, out] sample_actions
   13024                 :            :  *   Pointer to sample actions list.
   13025                 :            :  * @param[in, out] res
   13026                 :            :  *   Pointer to sample resource.
   13027                 :            :  * @param[out] error
   13028                 :            :  *   Pointer to the error structure.
   13029                 :            :  *
   13030                 :            :  * @return
   13031                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13032                 :            :  */
   13033                 :            : static int
   13034                 :          0 : flow_dv_translate_action_sample(struct rte_eth_dev *dev,
   13035                 :            :                                 const struct rte_flow_action_sample *action,
   13036                 :            :                                 struct mlx5_flow *dev_flow,
   13037                 :            :                                 const struct rte_flow_attr *attr,
   13038                 :            :                                 uint32_t *num_of_dest,
   13039                 :            :                                 void **sample_actions,
   13040                 :            :                                 struct mlx5_flow_dv_sample_resource *res,
   13041                 :            :                                 struct rte_flow_error *error)
   13042                 :            : {
   13043                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13044                 :            :         const struct rte_flow_action *sub_actions;
   13045                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   13046                 :            :         struct mlx5_flow_sub_actions_idx *sample_idx;
   13047                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   13048                 :          0 :         struct rte_flow *flow = dev_flow->flow;
   13049                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   13050                 :            :         uint64_t action_flags = 0;
   13051                 :            : 
   13052                 :            :         MLX5_ASSERT(wks);
   13053                 :          0 :         rss_desc = &wks->rss_desc;
   13054                 :            :         sample_act = &res->sample_act;
   13055                 :            :         sample_idx = &res->sample_idx;
   13056                 :          0 :         res->ratio = action->ratio;
   13057                 :          0 :         sub_actions = action->actions;
   13058         [ #  # ]:          0 :         for (; sub_actions->type != RTE_FLOW_ACTION_TYPE_END; sub_actions++) {
   13059                 :            :                 int type = sub_actions->type;
   13060                 :            :                 uint32_t pre_rix = 0;
   13061                 :            :                 void *pre_r;
   13062   [ #  #  #  #  :          0 :                 switch (type) {
                #  #  # ]
   13063                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   13064                 :            :                 {
   13065                 :            :                         const struct rte_flow_action_queue *queue;
   13066                 :            :                         struct mlx5_hrxq *hrxq;
   13067                 :            :                         uint32_t hrxq_idx;
   13068                 :            : 
   13069                 :          0 :                         queue = sub_actions->conf;
   13070                 :          0 :                         rss_desc->queue_num = 1;
   13071                 :          0 :                         rss_desc->queue[0] = queue->index;
   13072                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13073                 :            :                                                     rss_desc, &hrxq_idx);
   13074         [ #  # ]:          0 :                         if (!hrxq)
   13075                 :          0 :                                 return rte_flow_error_set
   13076                 :            :                                         (error, rte_errno,
   13077                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   13078                 :            :                                          NULL,
   13079                 :            :                                          "cannot create fate queue");
   13080                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13081                 :          0 :                         sample_idx->rix_hrxq = hrxq_idx;
   13082                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13083                 :            :                                                 hrxq->action;
   13084                 :          0 :                         (*num_of_dest)++;
   13085                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
   13086         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13087                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13088                 :          0 :                         dev_flow->handle->fate_action =
   13089                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   13090                 :          0 :                         break;
   13091                 :            :                 }
   13092                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   13093                 :            :                 {
   13094                 :            :                         struct mlx5_hrxq *hrxq;
   13095                 :            :                         uint32_t hrxq_idx;
   13096                 :            :                         const struct rte_flow_action_rss *rss;
   13097                 :            :                         const uint8_t *rss_key;
   13098                 :            : 
   13099                 :          0 :                         rss = sub_actions->conf;
   13100                 :          0 :                         rss_desc->symmetric_hash_function =
   13101                 :          0 :                                 MLX5_RSS_IS_SYMM(rss->func);
   13102                 :          0 :                         memcpy(rss_desc->queue, rss->queue,
   13103         [ #  # ]:          0 :                                rss->queue_num * sizeof(uint16_t));
   13104                 :          0 :                         rss_desc->queue_num = rss->queue_num;
   13105                 :            :                         /* NULL RSS key indicates default RSS key. */
   13106         [ #  # ]:          0 :                         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   13107                 :          0 :                         memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   13108                 :            :                         /*
   13109                 :            :                          * rss->level and rss.types should be set in advance
   13110                 :            :                          * when expanding items for RSS.
   13111                 :            :                          */
   13112                 :          0 :                         flow_dv_hashfields_set(dev_flow->handle->layers,
   13113                 :            :                                                rss_desc,
   13114                 :            :                                                &dev_flow->hash_fields);
   13115                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13116                 :            :                                                     rss_desc, &hrxq_idx);
   13117         [ #  # ]:          0 :                         if (!hrxq)
   13118                 :          0 :                                 return rte_flow_error_set
   13119                 :            :                                         (error, rte_errno,
   13120                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   13121                 :            :                                          NULL,
   13122                 :            :                                          "cannot create fate queue");
   13123                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13124                 :          0 :                         sample_idx->rix_hrxq = hrxq_idx;
   13125                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13126                 :            :                                                 hrxq->action;
   13127                 :          0 :                         (*num_of_dest)++;
   13128                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
   13129         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13130                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13131                 :          0 :                         dev_flow->handle->fate_action =
   13132                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   13133                 :          0 :                         break;
   13134                 :            :                 }
   13135                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
   13136                 :            :                 {
   13137                 :            :                         uint32_t tag_be = mlx5_flow_mark_set
   13138                 :            :                                 (((const struct rte_flow_action_mark *)
   13139         [ #  # ]:          0 :                                 (sub_actions->conf))->id);
   13140                 :            : 
   13141                 :          0 :                         wks->mark = 1;
   13142                 :          0 :                         pre_rix = dev_flow->handle->dvh.rix_tag;
   13143                 :            :                         /* Save the mark resource before sample */
   13144                 :          0 :                         pre_r = dev_flow->dv.tag_resource;
   13145         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   13146                 :            :                                                   dev_flow, error))
   13147                 :          0 :                                 return -rte_errno;
   13148                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   13149                 :          0 :                         sample_act->dr_tag_action =
   13150                 :          0 :                                 dev_flow->dv.tag_resource->action;
   13151                 :          0 :                         sample_idx->rix_tag =
   13152                 :          0 :                                 dev_flow->handle->dvh.rix_tag;
   13153                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13154                 :            :                                                 sample_act->dr_tag_action;
   13155                 :            :                         /* Recover the mark resource after sample */
   13156                 :          0 :                         dev_flow->dv.tag_resource = pre_r;
   13157                 :          0 :                         dev_flow->handle->dvh.rix_tag = pre_rix;
   13158                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
   13159                 :          0 :                         break;
   13160                 :            :                 }
   13161                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   13162                 :            :                 {
   13163         [ #  # ]:          0 :                         if (!flow->counter) {
   13164                 :          0 :                                 flow->counter =
   13165                 :          0 :                                         flow_dv_translate_create_counter(dev,
   13166                 :          0 :                                                 dev_flow, sub_actions->conf,
   13167                 :            :                                                 0);
   13168         [ #  # ]:          0 :                                 if (!flow->counter)
   13169                 :          0 :                                         return rte_flow_error_set
   13170                 :            :                                                 (error, rte_errno,
   13171                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   13172                 :            :                                                 NULL,
   13173                 :            :                                                 "cannot create counter"
   13174                 :            :                                                 " object.");
   13175                 :            :                         }
   13176                 :          0 :                         sample_act->dr_cnt_action =
   13177         [ #  # ]:          0 :                                   (flow_dv_counter_get_by_idx(dev,
   13178                 :          0 :                                   flow->counter, NULL))->action;
   13179                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13180                 :            :                                                 sample_act->dr_cnt_action;
   13181                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
   13182                 :          0 :                         break;
   13183                 :            :                 }
   13184                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
   13185                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   13186                 :            :                 {
   13187                 :            :                         struct mlx5_flow_dv_port_id_action_resource
   13188                 :            :                                         port_id_resource;
   13189                 :          0 :                         uint32_t port_id = 0;
   13190                 :            : 
   13191                 :            :                         memset(&port_id_resource, 0, sizeof(port_id_resource));
   13192                 :            :                         /* Save the port id resource before sample */
   13193                 :          0 :                         pre_rix = dev_flow->handle->rix_port_id_action;
   13194                 :          0 :                         pre_r = dev_flow->dv.port_id_action;
   13195         [ #  # ]:          0 :                         if (flow_dv_translate_action_port_id(dev, sub_actions,
   13196                 :            :                                                              &port_id, error))
   13197                 :          0 :                                 return -rte_errno;
   13198                 :          0 :                         port_id_resource.port_id = port_id;
   13199         [ #  # ]:          0 :                         if (flow_dv_port_id_action_resource_register
   13200                 :            :                             (dev, &port_id_resource, dev_flow, error))
   13201                 :          0 :                                 return -rte_errno;
   13202                 :          0 :                         sample_act->dr_port_id_action =
   13203                 :          0 :                                 dev_flow->dv.port_id_action->action;
   13204                 :          0 :                         sample_idx->rix_port_id_action =
   13205                 :          0 :                                 dev_flow->handle->rix_port_id_action;
   13206                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13207                 :            :                                                 sample_act->dr_port_id_action;
   13208                 :            :                         /* Recover the port id resource after sample */
   13209                 :          0 :                         dev_flow->dv.port_id_action = pre_r;
   13210                 :          0 :                         dev_flow->handle->rix_port_id_action = pre_rix;
   13211                 :          0 :                         (*num_of_dest)++;
   13212                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   13213                 :          0 :                         break;
   13214                 :            :                 }
   13215                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   13216                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   13217                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   13218                 :            :                         /* Save the encap resource before sample */
   13219                 :          0 :                         pre_rix = dev_flow->handle->dvh.rix_encap_decap;
   13220                 :          0 :                         pre_r = dev_flow->dv.encap_decap;
   13221         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_encap(dev, sub_actions,
   13222                 :            :                                                            dev_flow,
   13223                 :          0 :                                                            attr->transfer,
   13224                 :            :                                                            error))
   13225                 :          0 :                                 return -rte_errno;
   13226                 :          0 :                         sample_act->dr_encap_action =
   13227                 :          0 :                                 dev_flow->dv.encap_decap->action;
   13228                 :          0 :                         sample_idx->rix_encap_decap =
   13229                 :          0 :                                 dev_flow->handle->dvh.rix_encap_decap;
   13230                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13231                 :            :                                                 sample_act->dr_encap_action;
   13232                 :            :                         /* Recover the encap resource after sample */
   13233                 :          0 :                         dev_flow->dv.encap_decap = pre_r;
   13234                 :          0 :                         dev_flow->handle->dvh.rix_encap_decap = pre_rix;
   13235                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   13236                 :          0 :                         break;
   13237                 :          0 :                 default:
   13238                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13239                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13240                 :            :                                 NULL,
   13241                 :            :                                 "Not support for sampler action");
   13242                 :            :                 }
   13243                 :            :         }
   13244                 :          0 :         sample_act->action_flags = action_flags;
   13245                 :          0 :         res->ft_id = dev_flow->dv.group;
   13246         [ #  # ]:          0 :         if (attr->transfer) {
   13247                 :            :                 union {
   13248                 :            :                         uint32_t action_in[MLX5_ST_SZ_DW(set_action_in)];
   13249                 :            :                         uint64_t set_action;
   13250                 :            :                 } action_ctx = { .set_action = 0 };
   13251                 :          0 :                 uint32_t vport_meta_tag = wks->vport_meta_tag ?
   13252         [ #  # ]:          0 :                                           wks->vport_meta_tag :
   13253                 :            :                                           priv->vport_meta_tag;
   13254                 :            : 
   13255                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
   13256                 :            :                 MLX5_SET(set_action_in, action_ctx.action_in, action_type,
   13257                 :            :                          MLX5_MODIFICATION_TYPE_SET);
   13258         [ #  # ]:          0 :                 MLX5_SET(set_action_in, action_ctx.action_in, field,
   13259                 :            :                          MLX5_MODI_META_REG_C_0);
   13260                 :          0 :                 MLX5_SET(set_action_in, action_ctx.action_in, data,
   13261                 :            :                          vport_meta_tag);
   13262                 :          0 :                 res->set_action = action_ctx.set_action;
   13263         [ #  # ]:          0 :         } else if (attr->ingress) {
   13264                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   13265                 :            :         } else {
   13266                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX;
   13267                 :            :         }
   13268                 :            :         return 0;
   13269                 :            : }
   13270                 :            : 
   13271                 :            : static void *
   13272                 :          0 : flow_dv_translate_action_send_to_kernel(struct rte_eth_dev *dev,
   13273                 :            :                                         const struct rte_flow_attr *attr,
   13274                 :            :                                         struct rte_flow_error *error)
   13275                 :            : {
   13276                 :            :         struct mlx5_flow_tbl_resource *tbl;
   13277                 :            :         struct mlx5_dev_ctx_shared *sh;
   13278                 :            :         uint32_t priority;
   13279                 :            :         void *action;
   13280                 :            :         int ft_type;
   13281                 :            :         int ret;
   13282                 :            : 
   13283                 :          0 :         sh = MLX5_SH(dev);
   13284         [ #  # ]:          0 :         ft_type = (attr->ingress) ? MLX5DR_TABLE_TYPE_NIC_RX :
   13285         [ #  # ]:          0 :                   ((attr->transfer) ? MLX5DR_TABLE_TYPE_FDB :
   13286                 :            :                   MLX5DR_TABLE_TYPE_NIC_TX);
   13287         [ #  # ]:          0 :         if (sh->send_to_kernel_action[ft_type].action)
   13288                 :            :                 return sh->send_to_kernel_action[ft_type].action;
   13289                 :          0 :         priority = mlx5_get_send_to_kernel_priority(dev);
   13290         [ #  # ]:          0 :         if (priority == (uint32_t)-1) {
   13291                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   13292                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13293                 :            :                                    "required priority is not available");
   13294                 :          0 :                 return NULL;
   13295                 :            :         }
   13296                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, attr->egress, attr->transfer, false, NULL, 0, 0, 0,
   13297                 :            :                                        error);
   13298         [ #  # ]:          0 :         if (!tbl) {
   13299                 :          0 :                 rte_flow_error_set(error, ENODATA,
   13300                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13301                 :            :                                    "cannot find destination root table");
   13302                 :          0 :                 return NULL;
   13303                 :            :         }
   13304                 :          0 :         ret = mlx5_flow_os_create_flow_action_send_to_kernel(tbl->obj,
   13305                 :            :                                 priority, &action);
   13306                 :            :         if (ret) {
   13307                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   13308                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13309                 :            :                                    "cannot create action");
   13310                 :          0 :                 goto err;
   13311                 :            :         }
   13312                 :            :         MLX5_ASSERT(action);
   13313                 :          0 :         sh->send_to_kernel_action[ft_type].action = action;
   13314                 :          0 :         sh->send_to_kernel_action[ft_type].tbl = tbl;
   13315                 :          0 :         return action;
   13316                 :            : err:
   13317                 :          0 :         flow_dv_tbl_resource_release(sh, tbl);
   13318                 :          0 :         return NULL;
   13319                 :            : }
   13320                 :            : 
   13321                 :            : /**
   13322                 :            :  * Convert Sample action to DV specification.
   13323                 :            :  *
   13324                 :            :  * @param[in] dev
   13325                 :            :  *   Pointer to rte_eth_dev structure.
   13326                 :            :  * @param[in, out] dev_flow
   13327                 :            :  *   Pointer to the mlx5_flow.
   13328                 :            :  * @param[in] num_of_dest
   13329                 :            :  *   The num of destination.
   13330                 :            :  * @param[in, out] res
   13331                 :            :  *   Pointer to sample resource.
   13332                 :            :  * @param[in, out] mdest_res
   13333                 :            :  *   Pointer to destination array resource.
   13334                 :            :  * @param[in] sample_actions
   13335                 :            :  *   Pointer to sample path actions list.
   13336                 :            :  * @param[in] action_flags
   13337                 :            :  *   Holds the actions detected until now.
   13338                 :            :  * @param[out] error
   13339                 :            :  *   Pointer to the error structure.
   13340                 :            :  *
   13341                 :            :  * @return
   13342                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13343                 :            :  */
   13344                 :            : static int
   13345                 :          0 : flow_dv_create_action_sample(struct rte_eth_dev *dev,
   13346                 :            :                              struct mlx5_flow *dev_flow,
   13347                 :            :                              uint32_t num_of_dest,
   13348                 :            :                              struct mlx5_flow_dv_sample_resource *res,
   13349                 :            :                              struct mlx5_flow_dv_dest_array_resource *mdest_res,
   13350                 :            :                              void **sample_actions,
   13351                 :            :                              uint64_t action_flags,
   13352                 :            :                              struct rte_flow_error *error)
   13353                 :            : {
   13354                 :            :         /* update normal path action resource into last index of array */
   13355                 :            :         uint32_t dest_index = MLX5_MAX_DEST_NUM - 1;
   13356                 :            :         struct mlx5_flow_sub_actions_list *sample_act =
   13357                 :            :                                         &mdest_res->sample_act[dest_index];
   13358                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   13359                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   13360                 :            :         uint32_t normal_idx = 0;
   13361                 :            :         struct mlx5_hrxq *hrxq;
   13362                 :            :         uint32_t hrxq_idx;
   13363                 :            : 
   13364                 :            :         MLX5_ASSERT(wks);
   13365                 :          0 :         rss_desc = &wks->rss_desc;
   13366         [ #  # ]:          0 :         if (num_of_dest > 1) {
   13367         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_QUEUE) {
   13368                 :            :                         /* Handle QP action for mirroring */
   13369                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13370                 :            :                                                     rss_desc, &hrxq_idx);
   13371         [ #  # ]:          0 :                         if (!hrxq)
   13372                 :          0 :                                 return rte_flow_error_set
   13373                 :            :                                      (error, rte_errno,
   13374                 :            :                                       RTE_FLOW_ERROR_TYPE_ACTION,
   13375                 :            :                                       NULL,
   13376                 :            :                                       "cannot create rx queue");
   13377                 :            :                         normal_idx++;
   13378                 :          0 :                         mdest_res->sample_idx[dest_index].rix_hrxq = hrxq_idx;
   13379                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13380         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13381                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13382                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
   13383                 :            :                 }
   13384         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_ENCAP) {
   13385                 :          0 :                         normal_idx++;
   13386                 :          0 :                         mdest_res->sample_idx[dest_index].rix_encap_decap =
   13387                 :          0 :                                 dev_flow->handle->dvh.rix_encap_decap;
   13388                 :          0 :                         sample_act->dr_encap_action =
   13389                 :          0 :                                 dev_flow->dv.encap_decap->action;
   13390                 :          0 :                         dev_flow->handle->dvh.rix_encap_decap = 0;
   13391                 :            :                 }
   13392         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_PORT_ID) {
   13393                 :          0 :                         normal_idx++;
   13394                 :          0 :                         mdest_res->sample_idx[dest_index].rix_port_id_action =
   13395                 :          0 :                                 dev_flow->handle->rix_port_id_action;
   13396                 :          0 :                         sample_act->dr_port_id_action =
   13397                 :          0 :                                 dev_flow->dv.port_id_action->action;
   13398                 :          0 :                         dev_flow->handle->rix_port_id_action = 0;
   13399                 :            :                 }
   13400         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_JUMP) {
   13401                 :          0 :                         normal_idx++;
   13402                 :          0 :                         mdest_res->sample_idx[dest_index].rix_jump =
   13403                 :          0 :                                 dev_flow->handle->rix_jump;
   13404                 :          0 :                         sample_act->dr_jump_action =
   13405                 :          0 :                                 dev_flow->dv.jump->action;
   13406                 :          0 :                         dev_flow->handle->rix_jump = 0;
   13407                 :            :                 }
   13408                 :          0 :                 sample_act->actions_num = normal_idx;
   13409                 :            :                 /* update sample action resource into first index of array */
   13410                 :          0 :                 mdest_res->ft_type = res->ft_type;
   13411                 :          0 :                 memcpy(&mdest_res->sample_idx[0], &res->sample_idx,
   13412                 :            :                                 sizeof(struct mlx5_flow_sub_actions_idx));
   13413                 :          0 :                 memcpy(&mdest_res->sample_act[0], &res->sample_act,
   13414                 :            :                                 sizeof(struct mlx5_flow_sub_actions_list));
   13415                 :          0 :                 mdest_res->num_of_dest = num_of_dest;
   13416         [ #  # ]:          0 :                 if (flow_dv_dest_array_resource_register(dev, mdest_res,
   13417                 :            :                                                          dev_flow, error))
   13418                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13419                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   13420                 :            :                                                   NULL, "can't create sample "
   13421                 :            :                                                   "action");
   13422                 :            :         } else {
   13423                 :          0 :                 res->sub_actions = sample_actions;
   13424         [ #  # ]:          0 :                 if (flow_dv_sample_resource_register(dev, res, dev_flow, error))
   13425                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13426                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   13427                 :            :                                                   NULL,
   13428                 :            :                                                   "can't create sample action");
   13429                 :            :         }
   13430                 :            :         return 0;
   13431                 :            : }
   13432                 :            : 
   13433                 :            : /**
   13434                 :            :  * Remove an ASO age action from age actions list.
   13435                 :            :  *
   13436                 :            :  * @param[in] dev
   13437                 :            :  *   Pointer to the Ethernet device structure.
   13438                 :            :  * @param[in] age
   13439                 :            :  *   Pointer to the aso age action handler.
   13440                 :            :  */
   13441                 :            : static void
   13442                 :          0 : flow_dv_aso_age_remove_from_age(struct rte_eth_dev *dev,
   13443                 :            :                                 struct mlx5_aso_age_action *age)
   13444                 :            : {
   13445                 :            :         struct mlx5_age_info *age_info;
   13446                 :            :         struct mlx5_age_param *age_param = &age->age_params;
   13447                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13448                 :            :         uint16_t expected = AGE_CANDIDATE;
   13449                 :            : 
   13450                 :          0 :         age_info = GET_PORT_AGE_INFO(priv);
   13451         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&age_param->state, &expected,
   13452                 :            :                                          AGE_FREE, rte_memory_order_relaxed,
   13453                 :            :                                          rte_memory_order_relaxed)) {
   13454                 :            :                 /**
   13455                 :            :                  * We need the lock even it is age timeout,
   13456                 :            :                  * since age action may still in process.
   13457                 :            :                  */
   13458                 :          0 :                 rte_spinlock_lock(&age_info->aged_sl);
   13459         [ #  # ]:          0 :                 LIST_REMOVE(age, next);
   13460                 :            :                 rte_spinlock_unlock(&age_info->aged_sl);
   13461                 :          0 :                 rte_atomic_store_explicit(&age_param->state, AGE_FREE, rte_memory_order_relaxed);
   13462                 :            :         }
   13463                 :          0 : }
   13464                 :            : 
   13465                 :            : /**
   13466                 :            :  * Release an ASO age action.
   13467                 :            :  *
   13468                 :            :  * @param[in] dev
   13469                 :            :  *   Pointer to the Ethernet device structure.
   13470                 :            :  * @param[in] age_idx
   13471                 :            :  *   Index of ASO age action to release.
   13472                 :            :  * @param[in] flow
   13473                 :            :  *   True if the release operation is during flow destroy operation.
   13474                 :            :  *   False if the release operation is during action destroy operation.
   13475                 :            :  *
   13476                 :            :  * @return
   13477                 :            :  *   0 when age action was removed, otherwise the number of references.
   13478                 :            :  */
   13479                 :            : static int
   13480                 :          0 : flow_dv_aso_age_release(struct rte_eth_dev *dev, uint32_t age_idx)
   13481                 :            : {
   13482                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13483                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13484                 :          0 :         struct mlx5_aso_age_action *age = flow_aso_age_get_by_idx(dev, age_idx);
   13485                 :          0 :         uint32_t ret = rte_atomic_fetch_sub_explicit(&age->refcnt, 1, rte_memory_order_relaxed) - 1;
   13486                 :            : 
   13487         [ #  # ]:          0 :         if (!ret) {
   13488                 :          0 :                 flow_dv_aso_age_remove_from_age(dev, age);
   13489                 :          0 :                 rte_spinlock_lock(&mng->free_sl);
   13490         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free, age, next);
   13491                 :            :                 rte_spinlock_unlock(&mng->free_sl);
   13492                 :            :         }
   13493                 :          0 :         return ret;
   13494                 :            : }
   13495                 :            : 
   13496                 :            : /**
   13497                 :            :  * Resize the ASO age pools array by MLX5_ASO_AGE_CONTAINER_RESIZE pools.
   13498                 :            :  *
   13499                 :            :  * @param[in] dev
   13500                 :            :  *   Pointer to the Ethernet device structure.
   13501                 :            :  *
   13502                 :            :  * @return
   13503                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
   13504                 :            :  */
   13505                 :            : static int
   13506                 :          0 : flow_dv_aso_age_pools_resize(struct rte_eth_dev *dev)
   13507                 :            : {
   13508                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13509                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13510                 :          0 :         void *old_pools = mng->pools;
   13511                 :          0 :         uint32_t resize = mng->n + MLX5_ASO_AGE_CONTAINER_RESIZE;
   13512                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_age_pool *) * resize;
   13513                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   13514                 :            : 
   13515         [ #  # ]:          0 :         if (!pools) {
   13516                 :          0 :                 rte_errno = ENOMEM;
   13517                 :          0 :                 return -ENOMEM;
   13518                 :            :         }
   13519         [ #  # ]:          0 :         if (old_pools) {
   13520                 :          0 :                 memcpy(pools, old_pools,
   13521                 :          0 :                        mng->n * sizeof(struct mlx5_flow_counter_pool *));
   13522                 :          0 :                 mlx5_free(old_pools);
   13523                 :            :         } else {
   13524                 :            :                 /* First ASO flow hit allocation - starting ASO data-path. */
   13525                 :          0 :                 int ret = mlx5_aso_flow_hit_queue_poll_start(priv->sh);
   13526                 :            : 
   13527         [ #  # ]:          0 :                 if (ret) {
   13528                 :          0 :                         mlx5_free(pools);
   13529                 :          0 :                         return ret;
   13530                 :            :                 }
   13531                 :            :         }
   13532                 :          0 :         mng->n = resize;
   13533                 :          0 :         mng->pools = pools;
   13534                 :          0 :         return 0;
   13535                 :            : }
   13536                 :            : 
   13537                 :            : /**
   13538                 :            :  * Create and initialize a new ASO aging pool.
   13539                 :            :  *
   13540                 :            :  * @param[in] dev
   13541                 :            :  *   Pointer to the Ethernet device structure.
   13542                 :            :  * @param[out] age_free
   13543                 :            :  *   Where to put the pointer of a new age action.
   13544                 :            :  *
   13545                 :            :  * @return
   13546                 :            :  *   The age actions pool pointer and @p age_free is set on success,
   13547                 :            :  *   NULL otherwise and rte_errno is set.
   13548                 :            :  */
   13549                 :            : static struct mlx5_aso_age_pool *
   13550                 :          0 : flow_dv_age_pool_create(struct rte_eth_dev *dev,
   13551                 :            :                         struct mlx5_aso_age_action **age_free)
   13552                 :            : {
   13553                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13554                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13555                 :            :         struct mlx5_aso_age_pool *pool = NULL;
   13556                 :            :         struct mlx5_devx_obj *obj = NULL;
   13557                 :            :         uint32_t i;
   13558                 :            : 
   13559                 :          0 :         obj = mlx5_devx_cmd_create_flow_hit_aso_obj(priv->sh->cdev->ctx,
   13560                 :          0 :                                                     priv->sh->cdev->pdn);
   13561         [ #  # ]:          0 :         if (!obj) {
   13562                 :          0 :                 rte_errno = ENODATA;
   13563                 :          0 :                 DRV_LOG(ERR, "Failed to create flow_hit_aso_obj using DevX.");
   13564                 :          0 :                 return NULL;
   13565                 :            :         }
   13566                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY);
   13567         [ #  # ]:          0 :         if (!pool) {
   13568                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13569                 :          0 :                 rte_errno = ENOMEM;
   13570                 :          0 :                 return NULL;
   13571                 :            :         }
   13572                 :          0 :         pool->flow_hit_aso_obj = obj;
   13573                 :          0 :         pool->time_of_last_age_check = MLX5_CURR_TIME_SEC;
   13574                 :          0 :         rte_rwlock_write_lock(&mng->resize_rwl);
   13575                 :          0 :         pool->index = mng->next;
   13576                 :            :         /* Resize pools array if there is no room for the new pool in it. */
   13577   [ #  #  #  # ]:          0 :         if (pool->index == mng->n && flow_dv_aso_age_pools_resize(dev)) {
   13578                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13579                 :          0 :                 mlx5_free(pool);
   13580                 :            :                 rte_rwlock_write_unlock(&mng->resize_rwl);
   13581                 :          0 :                 return NULL;
   13582                 :            :         }
   13583                 :          0 :         mng->pools[pool->index] = pool;
   13584                 :          0 :         mng->next++;
   13585                 :            :         rte_rwlock_write_unlock(&mng->resize_rwl);
   13586                 :            :         /* Assign the first action in the new pool, the rest go to free list. */
   13587                 :          0 :         *age_free = &pool->actions[0];
   13588         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_AGE_ACTIONS_PER_POOL; i++) {
   13589                 :          0 :                 pool->actions[i].offset = i;
   13590         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free, &pool->actions[i], next);
   13591                 :            :         }
   13592                 :            :         return pool;
   13593                 :            : }
   13594                 :            : 
   13595                 :            : /**
   13596                 :            :  * Allocate a ASO aging bit.
   13597                 :            :  *
   13598                 :            :  * @param[in] dev
   13599                 :            :  *   Pointer to the Ethernet device structure.
   13600                 :            :  * @param[out] error
   13601                 :            :  *   Pointer to the error structure.
   13602                 :            :  *
   13603                 :            :  * @return
   13604                 :            :  *   Index to ASO age action on success, 0 otherwise and rte_errno is set.
   13605                 :            :  */
   13606                 :            : static uint32_t
   13607                 :          0 : flow_dv_aso_age_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error)
   13608                 :            : {
   13609                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13610                 :            :         const struct mlx5_aso_age_pool *pool;
   13611                 :          0 :         struct mlx5_aso_age_action *age_free = NULL;
   13612                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13613                 :            : 
   13614                 :            :         MLX5_ASSERT(mng);
   13615                 :            :         /* Try to get the next free age action bit. */
   13616                 :          0 :         rte_spinlock_lock(&mng->free_sl);
   13617                 :          0 :         age_free = LIST_FIRST(&mng->free);
   13618         [ #  # ]:          0 :         if (age_free) {
   13619         [ #  # ]:          0 :                 LIST_REMOVE(age_free, next);
   13620         [ #  # ]:          0 :         } else if (!flow_dv_age_pool_create(dev, &age_free)) {
   13621                 :            :                 rte_spinlock_unlock(&mng->free_sl);
   13622                 :          0 :                 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
   13623                 :            :                                    NULL, "failed to create ASO age pool");
   13624                 :          0 :                 return 0; /* 0 is an error. */
   13625                 :            :         }
   13626                 :            :         rte_spinlock_unlock(&mng->free_sl);
   13627                 :          0 :         pool = container_of
   13628                 :            :           ((const struct mlx5_aso_age_action (*)[MLX5_ASO_AGE_ACTIONS_PER_POOL])
   13629                 :            :                   (age_free - age_free->offset), const struct mlx5_aso_age_pool,
   13630                 :            :                                                                        actions);
   13631         [ #  # ]:          0 :         if (!age_free->dr_action) {
   13632                 :          0 :                 int reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_FLOW_HIT, 0,
   13633                 :            :                                                  error);
   13634                 :            : 
   13635         [ #  # ]:          0 :                 if (reg_c < 0) {
   13636                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13637                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   13638                 :            :                                            NULL, "failed to get reg_c "
   13639                 :            :                                            "for ASO flow hit");
   13640                 :          0 :                         return 0; /* 0 is an error. */
   13641                 :            :                 }
   13642                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
   13643                 :          0 :                 age_free->dr_action = mlx5_glue->dv_create_flow_action_aso
   13644                 :          0 :                                 (priv->sh->rx_domain,
   13645                 :          0 :                                  pool->flow_hit_aso_obj->obj, age_free->offset,
   13646                 :            :                                  MLX5DV_DR_ACTION_FLAGS_ASO_FIRST_HIT_SET,
   13647                 :          0 :                                  (reg_c - REG_C_0));
   13648                 :            : #endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
   13649         [ #  # ]:          0 :                 if (!age_free->dr_action) {
   13650                 :          0 :                         rte_errno = errno;
   13651                 :            :                         rte_spinlock_lock(&mng->free_sl);
   13652         [ #  # ]:          0 :                         LIST_INSERT_HEAD(&mng->free, age_free, next);
   13653                 :            :                         rte_spinlock_unlock(&mng->free_sl);
   13654                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13655                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   13656                 :            :                                            NULL, "failed to create ASO "
   13657                 :            :                                            "flow hit action");
   13658                 :          0 :                         return 0; /* 0 is an error. */
   13659                 :            :                 }
   13660                 :            :         }
   13661                 :          0 :         rte_atomic_store_explicit(&age_free->refcnt, 1, rte_memory_order_relaxed);
   13662                 :          0 :         return pool->index | ((age_free->offset + 1) << 16);
   13663                 :            : }
   13664                 :            : 
   13665                 :            : /**
   13666                 :            :  * Initialize flow ASO age parameters.
   13667                 :            :  *
   13668                 :            :  * @param[in] dev
   13669                 :            :  *   Pointer to rte_eth_dev structure.
   13670                 :            :  * @param[in] age_idx
   13671                 :            :  *   Index of ASO age action.
   13672                 :            :  * @param[in] context
   13673                 :            :  *   Pointer to flow counter age context.
   13674                 :            :  * @param[in] timeout
   13675                 :            :  *   Aging timeout in seconds.
   13676                 :            :  *
   13677                 :            :  */
   13678                 :            : static void
   13679                 :          0 : flow_dv_aso_age_params_init(struct rte_eth_dev *dev,
   13680                 :            :                             uint32_t age_idx,
   13681                 :            :                             void *context,
   13682                 :            :                             uint32_t timeout)
   13683                 :            : {
   13684                 :            :         struct mlx5_aso_age_action *aso_age;
   13685                 :            : 
   13686                 :          0 :         aso_age = flow_aso_age_get_by_idx(dev, age_idx);
   13687                 :            :         MLX5_ASSERT(aso_age);
   13688                 :          0 :         aso_age->age_params.context = context;
   13689                 :          0 :         aso_age->age_params.timeout = timeout;
   13690                 :          0 :         aso_age->age_params.port_id = dev->data->port_id;
   13691                 :          0 :         rte_atomic_store_explicit(&aso_age->age_params.sec_since_last_hit, 0,
   13692                 :            :                          rte_memory_order_relaxed);
   13693                 :          0 :         rte_atomic_store_explicit(&aso_age->age_params.state, AGE_CANDIDATE,
   13694                 :            :                          rte_memory_order_relaxed);
   13695                 :          0 : }
   13696                 :            : 
   13697                 :            : static void
   13698                 :          0 : flow_dv_translate_integrity_l4(const struct rte_flow_item_integrity *mask,
   13699                 :            :                                void *headers)
   13700                 :            : {
   13701                 :            :         /*
   13702                 :            :          * In HWS mode MLX5_ITEM_UPDATE() macro assigns the same pointer to
   13703                 :            :          * both mask and value, therefore ether can be used.
   13704                 :            :          * In SWS SW_V mode mask points to item mask and value points to item
   13705                 :            :          * spec. Integrity item value is used only if matching mask is set.
   13706                 :            :          * Use mask reference here to keep SWS functionality.
   13707                 :            :          */
   13708         [ #  # ]:          0 :         if (mask->l4_ok) {
   13709                 :            :                 /* RTE l4_ok filter aggregates hardware l4_ok and
   13710                 :            :                  * l4_checksum_ok filters.
   13711                 :            :                  * Positive RTE l4_ok match requires hardware match on both L4
   13712                 :            :                  * hardware integrity bits.
   13713                 :            :                  * PMD supports positive integrity item semantics only.
   13714                 :            :                  */
   13715         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_ok, 1);
   13716         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_checksum_ok, 1);
   13717         [ #  # ]:          0 :         } else if (mask->l4_csum_ok) {
   13718         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_checksum_ok, 1);
   13719                 :            :         }
   13720                 :          0 : }
   13721                 :            : 
   13722                 :            : static void
   13723                 :          0 : flow_dv_translate_integrity_l3(const struct rte_flow_item_integrity *mask,
   13724                 :            :                                void *headers, bool is_ipv4)
   13725                 :            : {
   13726                 :            :         /*
   13727                 :            :          * In HWS mode MLX5_ITEM_UPDATE() macro assigns the same pointer to
   13728                 :            :          * both mask and value, therefore ether can be used.
   13729                 :            :          * In SWS SW_V mode mask points to item mask and value points to item
   13730                 :            :          * spec. Integrity item value used only if matching mask is set.
   13731                 :            :          * Use mask reference here to keep SWS functionality.
   13732                 :            :          */
   13733         [ #  # ]:          0 :         if (mask->l3_ok) {
   13734                 :            :                 /* RTE l3_ok filter aggregates for IPv4 hardware l3_ok and
   13735                 :            :                  * ipv4_csum_ok filters.
   13736                 :            :                  * Positive RTE l3_ok match requires hardware match on both L3
   13737                 :            :                  * hardware integrity bits.
   13738                 :            :                  * PMD supports positive integrity item semantics only.
   13739                 :            :                  */
   13740         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l3_ok, 1);
   13741         [ #  # ]:          0 :                 if (is_ipv4) {
   13742         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers,
   13743                 :            :                                  ipv4_checksum_ok, 1);
   13744                 :            :                 }
   13745   [ #  #  #  # ]:          0 :         } else if (is_ipv4 && mask->ipv4_csum_ok) {
   13746         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, ipv4_checksum_ok, 1);
   13747                 :            :         }
   13748                 :          0 : }
   13749                 :            : 
   13750                 :            : static void
   13751                 :          0 : set_integrity_bits(void *headers, const struct rte_flow_item *integrity_item,
   13752                 :            :                    bool is_l3_ip4, uint32_t key_type)
   13753                 :            : {
   13754                 :            :         const struct rte_flow_item_integrity *spec;
   13755                 :            :         const struct rte_flow_item_integrity *mask;
   13756                 :            : 
   13757                 :            :         /* Integrity bits validation cleared spec pointer */
   13758   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(integrity_item, key_type))
          #  #  #  #  #  
                      # ]
   13759                 :            :                 return;
   13760   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(integrity_item, key_type, spec, mask,
             #  #  #  # ]
   13761                 :            :                          &rte_flow_item_integrity_mask);
   13762                 :          0 :         flow_dv_translate_integrity_l3(mask, headers, is_l3_ip4);
   13763                 :          0 :         flow_dv_translate_integrity_l4(mask, headers);
   13764                 :            : }
   13765                 :            : 
   13766                 :            : static void
   13767                 :          0 : flow_dv_translate_item_integrity_post(void *key,
   13768                 :            :                                       const
   13769                 :            :                                       struct rte_flow_item *integrity_items[2],
   13770                 :            :                                       uint64_t pattern_flags, uint32_t key_type)
   13771                 :            : {
   13772                 :            :         void *headers;
   13773                 :            :         bool is_l3_ip4;
   13774                 :            : 
   13775         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY) {
   13776                 :          0 :                 headers = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
   13777                 :          0 :                 is_l3_ip4 = (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV4) !=
   13778                 :            :                             0;
   13779                 :          0 :                 set_integrity_bits(headers, integrity_items[1], is_l3_ip4,
   13780                 :            :                                    key_type);
   13781                 :            :         }
   13782         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY) {
   13783                 :            :                 headers = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   13784                 :          0 :                 is_l3_ip4 = (pattern_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4) !=
   13785                 :            :                             0;
   13786                 :          0 :                 set_integrity_bits(headers, integrity_items[0], is_l3_ip4,
   13787                 :            :                                    key_type);
   13788                 :            :         }
   13789                 :          0 : }
   13790                 :            : 
   13791                 :            : static uint64_t
   13792                 :            : flow_dv_translate_item_integrity(const struct rte_flow_item *item,
   13793                 :            :                                  struct mlx5_dv_matcher_workspace *wks,
   13794                 :            :                                  uint64_t key_type)
   13795                 :            : {
   13796                 :          0 :         if ((key_type & MLX5_SET_MATCHER_SW) != 0) {
   13797                 :            :                 const struct rte_flow_item_integrity
   13798                 :          0 :                         *spec = (typeof(spec))item->spec;
   13799                 :            : 
   13800                 :            :                 /* SWS integrity bits validation cleared spec pointer */
   13801         [ #  # ]:          0 :                 if (spec->level > 1) {
   13802                 :          0 :                         wks->integrity_items[1] = item;
   13803                 :          0 :                         wks->last_item |= MLX5_FLOW_ITEM_INNER_INTEGRITY;
   13804                 :            :                 } else {
   13805                 :          0 :                         wks->integrity_items[0] = item;
   13806                 :          0 :                         wks->last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
   13807                 :            :                 }
   13808                 :            :         } else {
   13809                 :            :                 /* HWS supports outer integrity only */
   13810                 :          0 :                 wks->integrity_items[0] = item;
   13811                 :          0 :                 wks->last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
   13812                 :            :         }
   13813                 :          0 :         return wks->last_item;
   13814                 :            : }
   13815                 :            : 
   13816                 :            : /**
   13817                 :            :  * Prepares DV flow counter with aging configuration.
   13818                 :            :  * Gets it by index when exists, creates a new one when doesn't.
   13819                 :            :  *
   13820                 :            :  * @param[in] dev
   13821                 :            :  *   Pointer to rte_eth_dev structure.
   13822                 :            :  * @param[in] dev_flow
   13823                 :            :  *   Pointer to the mlx5_flow.
   13824                 :            :  * @param[in, out] flow
   13825                 :            :  *   Pointer to the sub flow.
   13826                 :            :  * @param[in] count
   13827                 :            :  *   Pointer to the counter action configuration.
   13828                 :            :  * @param[in] age
   13829                 :            :  *   Pointer to the aging action configuration.
   13830                 :            :  * @param[out] error
   13831                 :            :  *   Pointer to the error structure.
   13832                 :            :  *
   13833                 :            :  * @return
   13834                 :            :  *   Pointer to the counter, NULL otherwise.
   13835                 :            :  */
   13836                 :            : static struct mlx5_flow_counter *
   13837                 :          0 : flow_dv_prepare_counter(struct rte_eth_dev *dev,
   13838                 :            :                         struct mlx5_flow *dev_flow,
   13839                 :            :                         struct rte_flow *flow,
   13840                 :            :                         const struct rte_flow_action_count *count,
   13841                 :            :                         const struct rte_flow_action_age *age,
   13842                 :            :                         struct rte_flow_error *error)
   13843                 :            : {
   13844         [ #  # ]:          0 :         if (!flow->counter) {
   13845                 :          0 :                 flow->counter = flow_dv_translate_create_counter(dev, dev_flow,
   13846                 :            :                                                                  count, age);
   13847         [ #  # ]:          0 :                 if (!flow->counter) {
   13848                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13849                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13850                 :            :                                            "cannot create counter object.");
   13851                 :          0 :                         return NULL;
   13852                 :            :                 }
   13853                 :            :         }
   13854         [ #  # ]:          0 :         return flow_dv_counter_get_by_idx(dev, flow->counter, NULL);
   13855                 :            : }
   13856                 :            : 
   13857                 :            : /*
   13858                 :            :  * Release an ASO CT action by its own device.
   13859                 :            :  *
   13860                 :            :  * @param[in] dev
   13861                 :            :  *   Pointer to the Ethernet device structure.
   13862                 :            :  * @param[in] idx
   13863                 :            :  *   Index of ASO CT action to release.
   13864                 :            :  *
   13865                 :            :  * @return
   13866                 :            :  *   0 when CT action was removed, otherwise the number of references.
   13867                 :            :  */
   13868                 :            : static inline int
   13869                 :          0 : flow_dv_aso_ct_dev_release(struct rte_eth_dev *dev, uint32_t idx)
   13870                 :            : {
   13871                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13872                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13873                 :            :         uint32_t ret;
   13874                 :          0 :         struct mlx5_aso_ct_action *ct = flow_aso_ct_get_by_dev_idx(dev, idx);
   13875                 :            :         enum mlx5_aso_ct_state state =
   13876                 :          0 :                         rte_atomic_load_explicit(&ct->state, rte_memory_order_relaxed);
   13877                 :            : 
   13878                 :            :         /* Cannot release when CT is in the ASO SQ. */
   13879         [ #  # ]:          0 :         if (state == ASO_CONNTRACK_WAIT || state == ASO_CONNTRACK_QUERY)
   13880                 :            :                 return -1;
   13881                 :          0 :         ret = rte_atomic_fetch_sub_explicit(&ct->refcnt, 1, rte_memory_order_relaxed) - 1;
   13882         [ #  # ]:          0 :         if (!ret) {
   13883         [ #  # ]:          0 :                 if (ct->dr_action_orig) {
   13884                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13885                 :          0 :                         claim_zero(mlx5_glue->destroy_flow_action
   13886                 :            :                                         (ct->dr_action_orig));
   13887                 :            : #endif
   13888                 :          0 :                         ct->dr_action_orig = NULL;
   13889                 :            :                 }
   13890         [ #  # ]:          0 :                 if (ct->dr_action_rply) {
   13891                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13892                 :          0 :                         claim_zero(mlx5_glue->destroy_flow_action
   13893                 :            :                                         (ct->dr_action_rply));
   13894                 :            : #endif
   13895                 :          0 :                         ct->dr_action_rply = NULL;
   13896                 :            :                 }
   13897                 :            :                 /* Clear the state to free, no need in 1st allocation. */
   13898                 :          0 :                 MLX5_ASO_CT_UPDATE_STATE(ct, ASO_CONNTRACK_FREE);
   13899                 :          0 :                 rte_spinlock_lock(&mng->ct_sl);
   13900         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free_cts, ct, next);
   13901                 :            :                 rte_spinlock_unlock(&mng->ct_sl);
   13902                 :            :         }
   13903                 :          0 :         return (int)ret;
   13904                 :            : }
   13905                 :            : 
   13906                 :            : static inline int
   13907                 :          0 : flow_dv_aso_ct_release(struct rte_eth_dev *dev, uint32_t own_idx,
   13908                 :            :                        struct rte_flow_error *error)
   13909                 :            : {
   13910                 :          0 :         uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(own_idx);
   13911                 :          0 :         uint32_t idx = MLX5_INDIRECT_ACT_CT_GET_IDX(own_idx);
   13912                 :          0 :         struct rte_eth_dev *owndev = &rte_eth_devices[owner];
   13913                 :            :         int ret;
   13914                 :            : 
   13915                 :            :         MLX5_ASSERT(owner < RTE_MAX_ETHPORTS);
   13916         [ #  # ]:          0 :         if (dev->data->dev_started != 1)
   13917                 :          0 :                 return rte_flow_error_set(error, EAGAIN,
   13918                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   13919                 :            :                                           NULL,
   13920                 :            :                                           "Indirect CT action cannot be destroyed when the port is stopped");
   13921                 :          0 :         ret = flow_dv_aso_ct_dev_release(owndev, idx);
   13922         [ #  # ]:          0 :         if (ret < 0)
   13923                 :          0 :                 return rte_flow_error_set(error, EAGAIN,
   13924                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   13925                 :            :                                           NULL,
   13926                 :            :                                           "Current state prevents indirect CT action from being destroyed");
   13927                 :            :         return ret;
   13928                 :            : }
   13929                 :            : 
   13930                 :            : /*
   13931                 :            :  * Resize the ASO CT pools array by 64 pools.
   13932                 :            :  *
   13933                 :            :  * @param[in] dev
   13934                 :            :  *   Pointer to the Ethernet device structure.
   13935                 :            :  *
   13936                 :            :  * @return
   13937                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
   13938                 :            :  */
   13939                 :            : static int
   13940                 :          0 : flow_dv_aso_ct_pools_resize(struct rte_eth_dev *dev)
   13941                 :            : {
   13942                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13943                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13944                 :          0 :         void *old_pools = mng->pools;
   13945                 :            :         /* Magic number now, need a macro. */
   13946                 :          0 :         uint32_t resize = mng->n + 64;
   13947                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_ct_pool *) * resize;
   13948                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   13949                 :            : 
   13950         [ #  # ]:          0 :         if (!pools) {
   13951                 :          0 :                 rte_errno = ENOMEM;
   13952                 :          0 :                 return -rte_errno;
   13953                 :            :         }
   13954                 :          0 :         rte_rwlock_write_lock(&mng->resize_rwl);
   13955                 :            :         /* ASO SQ/QP was already initialized in the startup. */
   13956         [ #  # ]:          0 :         if (old_pools) {
   13957                 :            :                 /* Realloc could be an alternative choice. */
   13958                 :          0 :                 rte_memcpy(pools, old_pools,
   13959         [ #  # ]:          0 :                            mng->n * sizeof(struct mlx5_aso_ct_pool *));
   13960                 :          0 :                 mlx5_free(old_pools);
   13961                 :            :         }
   13962                 :          0 :         mng->n = resize;
   13963                 :          0 :         mng->pools = pools;
   13964                 :            :         rte_rwlock_write_unlock(&mng->resize_rwl);
   13965                 :          0 :         return 0;
   13966                 :            : }
   13967                 :            : 
   13968                 :            : /*
   13969                 :            :  * Create and initialize a new ASO CT pool.
   13970                 :            :  *
   13971                 :            :  * @param[in] dev
   13972                 :            :  *   Pointer to the Ethernet device structure.
   13973                 :            :  * @param[out] ct_free
   13974                 :            :  *   Where to put the pointer of a new CT action.
   13975                 :            :  *
   13976                 :            :  * @return
   13977                 :            :  *   The CT actions pool pointer and @p ct_free is set on success,
   13978                 :            :  *   NULL otherwise and rte_errno is set.
   13979                 :            :  */
   13980                 :            : static struct mlx5_aso_ct_pool *
   13981                 :          0 : flow_dv_ct_pool_create(struct rte_eth_dev *dev,
   13982                 :            :                        struct mlx5_aso_ct_action **ct_free)
   13983                 :            : {
   13984                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13985                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13986                 :            :         struct mlx5_aso_ct_pool *pool = NULL;
   13987                 :            :         struct mlx5_devx_obj *obj = NULL;
   13988                 :            :         uint32_t i;
   13989                 :            :         uint32_t log_obj_size = rte_log2_u32(MLX5_ASO_CT_ACTIONS_PER_POOL);
   13990                 :            :         size_t mem_size;
   13991                 :            : 
   13992                 :          0 :         obj = mlx5_devx_cmd_create_conn_track_offload_obj(priv->sh->cdev->ctx,
   13993                 :          0 :                                                           priv->sh->cdev->pdn,
   13994                 :            :                                                           log_obj_size);
   13995         [ #  # ]:          0 :         if (!obj) {
   13996                 :          0 :                 rte_errno = ENODATA;
   13997                 :          0 :                 DRV_LOG(ERR, "Failed to create conn_track_offload_obj using DevX.");
   13998                 :          0 :                 return NULL;
   13999                 :            :         }
   14000                 :            :         mem_size = sizeof(struct mlx5_aso_ct_action) *
   14001                 :            :                    MLX5_ASO_CT_ACTIONS_PER_POOL +
   14002                 :            :                    sizeof(*pool);
   14003                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   14004         [ #  # ]:          0 :         if (!pool) {
   14005                 :          0 :                 rte_errno = ENOMEM;
   14006                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   14007                 :          0 :                 return NULL;
   14008                 :            :         }
   14009                 :          0 :         pool->devx_obj = obj;
   14010                 :          0 :         pool->index = mng->next;
   14011                 :            :         /* Resize pools array if there is no room for the new pool in it. */
   14012   [ #  #  #  # ]:          0 :         if (pool->index == mng->n && flow_dv_aso_ct_pools_resize(dev)) {
   14013                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   14014                 :          0 :                 mlx5_free(pool);
   14015                 :          0 :                 return NULL;
   14016                 :            :         }
   14017                 :          0 :         mng->pools[pool->index] = pool;
   14018                 :          0 :         mng->next++;
   14019                 :            :         /* Assign the first action in the new pool, the rest go to free list. */
   14020                 :          0 :         *ct_free = &pool->actions[0];
   14021                 :            :         /* Lock outside, the list operation is safe here. */
   14022         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_CT_ACTIONS_PER_POOL; i++) {
   14023                 :            :                 /* refcnt is 0 when allocating the memory. */
   14024                 :          0 :                 pool->actions[i].offset = i;
   14025         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free_cts, &pool->actions[i], next);
   14026                 :            :         }
   14027                 :            :         return pool;
   14028                 :            : }
   14029                 :            : 
   14030                 :            : /*
   14031                 :            :  * Allocate a ASO CT action from free list.
   14032                 :            :  *
   14033                 :            :  * @param[in] dev
   14034                 :            :  *   Pointer to the Ethernet device structure.
   14035                 :            :  * @param[out] error
   14036                 :            :  *   Pointer to the error structure.
   14037                 :            :  *
   14038                 :            :  * @return
   14039                 :            :  *   Index to ASO CT action on success, 0 otherwise and rte_errno is set.
   14040                 :            :  */
   14041                 :            : static uint32_t
   14042                 :          0 : flow_dv_aso_ct_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error)
   14043                 :            : {
   14044                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14045                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   14046                 :          0 :         struct mlx5_aso_ct_action *ct = NULL;
   14047                 :            :         struct mlx5_aso_ct_pool *pool;
   14048                 :            :         uint8_t reg_c;
   14049                 :            :         uint32_t ct_idx;
   14050                 :            : 
   14051                 :            :         MLX5_ASSERT(mng);
   14052         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
   14053                 :          0 :                 rte_errno = ENOTSUP;
   14054                 :          0 :                 return 0;
   14055                 :            :         }
   14056                 :            :         /* Get a free CT action, if no, a new pool will be created. */
   14057                 :          0 :         rte_spinlock_lock(&mng->ct_sl);
   14058                 :          0 :         ct = LIST_FIRST(&mng->free_cts);
   14059         [ #  # ]:          0 :         if (ct) {
   14060         [ #  # ]:          0 :                 LIST_REMOVE(ct, next);
   14061         [ #  # ]:          0 :         } else if (!flow_dv_ct_pool_create(dev, &ct)) {
   14062                 :            :                 rte_spinlock_unlock(&mng->ct_sl);
   14063                 :          0 :                 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
   14064                 :            :                                    NULL, "failed to create ASO CT pool");
   14065                 :          0 :                 return 0;
   14066                 :            :         }
   14067                 :            :         rte_spinlock_unlock(&mng->ct_sl);
   14068                 :          0 :         pool = container_of(ct, struct mlx5_aso_ct_pool, actions[ct->offset]);
   14069                 :          0 :         ct_idx = MLX5_MAKE_CT_IDX(pool->index, ct->offset);
   14070                 :            :         /* 0: inactive, 1: created, 2+: used by flows. */
   14071                 :          0 :         rte_atomic_store_explicit(&ct->refcnt, 1, rte_memory_order_relaxed);
   14072                 :          0 :         reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, error);
   14073         [ #  # ]:          0 :         if (!ct->dr_action_orig) {
   14074                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   14075                 :          0 :                 ct->dr_action_orig = mlx5_glue->dv_create_flow_action_aso
   14076                 :          0 :                         (priv->sh->rx_domain, pool->devx_obj->obj,
   14077                 :            :                          ct->offset,
   14078                 :            :                          MLX5DV_DR_ACTION_FLAGS_ASO_CT_DIRECTION_INITIATOR,
   14079                 :          0 :                          reg_c - REG_C_0);
   14080                 :            : #else
   14081                 :            :                 RTE_SET_USED(reg_c);
   14082                 :            : #endif
   14083         [ #  # ]:          0 :                 if (!ct->dr_action_orig) {
   14084                 :          0 :                         flow_dv_aso_ct_dev_release(dev, ct_idx);
   14085                 :          0 :                         rte_flow_error_set(error, rte_errno,
   14086                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14087                 :            :                                            "failed to create ASO CT action");
   14088                 :          0 :                         return 0;
   14089                 :            :                 }
   14090                 :            :         }
   14091         [ #  # ]:          0 :         if (!ct->dr_action_rply) {
   14092                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   14093                 :          0 :                 ct->dr_action_rply = mlx5_glue->dv_create_flow_action_aso
   14094                 :          0 :                         (priv->sh->rx_domain, pool->devx_obj->obj,
   14095                 :            :                          ct->offset,
   14096                 :            :                          MLX5DV_DR_ACTION_FLAGS_ASO_CT_DIRECTION_RESPONDER,
   14097                 :          0 :                          reg_c - REG_C_0);
   14098                 :            : #endif
   14099         [ #  # ]:          0 :                 if (!ct->dr_action_rply) {
   14100                 :          0 :                         flow_dv_aso_ct_dev_release(dev, ct_idx);
   14101                 :          0 :                         rte_flow_error_set(error, rte_errno,
   14102                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14103                 :            :                                            "failed to create ASO CT action");
   14104                 :          0 :                         return 0;
   14105                 :            :                 }
   14106                 :            :         }
   14107                 :            :         return ct_idx;
   14108                 :            : }
   14109                 :            : 
   14110                 :            : /*
   14111                 :            :  * Create a conntrack object with context and actions by using ASO mechanism.
   14112                 :            :  *
   14113                 :            :  * @param[in] dev
   14114                 :            :  *   Pointer to rte_eth_dev structure.
   14115                 :            :  * @param[in] pro
   14116                 :            :  *   Pointer to conntrack information profile.
   14117                 :            :  * @param[out] error
   14118                 :            :  *   Pointer to the error structure.
   14119                 :            :  *
   14120                 :            :  * @return
   14121                 :            :  *   Index to conntrack object on success, 0 otherwise.
   14122                 :            :  */
   14123                 :            : static uint32_t
   14124                 :          0 : flow_dv_translate_create_conntrack(struct rte_eth_dev *dev,
   14125                 :            :                                    const struct rte_flow_action_conntrack *pro,
   14126                 :            :                                    struct rte_flow_error *error)
   14127                 :            : {
   14128                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14129                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   14130                 :            :         struct mlx5_aso_ct_action *ct;
   14131                 :            :         uint32_t idx;
   14132                 :            : 
   14133         [ #  # ]:          0 :         if (!sh->ct_aso_en)
   14134                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   14135                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14136                 :            :                                           "Connection is not supported");
   14137         [ #  # ]:          0 :         if (dev->data->port_id >= MLX5_INDIRECT_ACT_CT_MAX_PORT) {
   14138                 :          0 :                 rte_flow_error_set(error, EINVAL,
   14139                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   14140                 :            :                                    "CT supports port indexes up to "
   14141                 :            :                                    RTE_STR(MLX5_ACTION_CTX_CT_MAX_PORT));
   14142                 :          0 :                 return 0;
   14143                 :            :         }
   14144                 :          0 :         idx = flow_dv_aso_ct_alloc(dev, error);
   14145         [ #  # ]:          0 :         if (!idx)
   14146                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   14147                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14148                 :            :                                           "Failed to allocate CT object");
   14149                 :          0 :         ct = flow_aso_ct_get_by_dev_idx(dev, idx);
   14150         [ #  # ]:          0 :         if (mlx5_aso_ct_update_by_wqe(sh, MLX5_HW_INV_QUEUE, ct, pro, NULL, true)) {
   14151                 :          0 :                 flow_dv_aso_ct_dev_release(dev, idx);
   14152                 :          0 :                 rte_flow_error_set(error, EBUSY,
   14153                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14154                 :            :                                    "Failed to update CT");
   14155                 :          0 :                 return 0;
   14156                 :            :         }
   14157                 :          0 :         ct->is_original = !!pro->is_original_dir;
   14158                 :          0 :         ct->peer = pro->peer_port;
   14159                 :          0 :         return idx;
   14160                 :            : }
   14161                 :            : 
   14162                 :            : /**
   14163                 :            :  * Fill the flow matcher with DV spec.
   14164                 :            :  *
   14165                 :            :  * @param[in] dev
   14166                 :            :  *   Pointer to rte_eth_dev structure.
   14167                 :            :  * @param[in] items
   14168                 :            :  *   Pointer to the list of items.
   14169                 :            :  * @param[in] wks
   14170                 :            :  *   Pointer to the matcher workspace.
   14171                 :            :  * @param[in] key
   14172                 :            :  *   Pointer to the flow matcher key.
   14173                 :            :  * @param[in] key_type
   14174                 :            :  *   Key type.
   14175                 :            :  * @param[out] error
   14176                 :            :  *   Pointer to the error structure.
   14177                 :            :  *
   14178                 :            :  * @return
   14179                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14180                 :            :  */
   14181                 :            : static int
   14182                 :          0 : flow_dv_translate_items(struct rte_eth_dev *dev,
   14183                 :            :                         const struct rte_flow_item *items,
   14184                 :            :                         struct mlx5_dv_matcher_workspace *wks,
   14185                 :            :                         void *key, uint32_t key_type,
   14186                 :            :                         struct rte_flow_error *error)
   14187                 :            : {
   14188                 :          0 :         struct mlx5_flow_rss_desc *rss_desc = wks->rss_desc;
   14189                 :          0 :         uint8_t next_protocol = wks->next_protocol;
   14190                 :          0 :         int tunnel = !!(wks->item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14191                 :          0 :         int item_type = items->type;
   14192                 :          0 :         uint64_t last_item = wks->last_item;
   14193                 :            :         enum mlx5_l3_tunnel_detection l3_tunnel_detection;
   14194                 :            :         uint64_t l3_tunnel_flag;
   14195                 :            :         int ret;
   14196                 :            : 
   14197   [ #  #  #  #  :          0 :         switch (item_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
   14198                 :          0 :         case RTE_FLOW_ITEM_TYPE_ESP:
   14199                 :          0 :                 flow_dv_translate_item_esp(key, items, tunnel, key_type);
   14200                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14201                 :            :                 last_item = MLX5_FLOW_ITEM_ESP;
   14202                 :          0 :                 break;
   14203                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_ID:
   14204                 :          0 :                 flow_dv_translate_item_port_id
   14205                 :            :                         (dev, key, items, wks->attr, key_type);
   14206                 :            :                 last_item = MLX5_FLOW_ITEM_PORT_ID;
   14207                 :          0 :                 break;
   14208                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
   14209                 :          0 :                 flow_dv_translate_item_port_representor
   14210                 :            :                         (dev, key, key_type);
   14211                 :            :                 last_item = MLX5_FLOW_ITEM_PORT_REPRESENTOR;
   14212                 :          0 :                 break;
   14213                 :          0 :         case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
   14214                 :          0 :                 flow_dv_translate_item_represented_port
   14215                 :            :                         (dev, key, items, wks->attr, key_type);
   14216                 :            :                 last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
   14217                 :          0 :                 break;
   14218                 :          0 :         case RTE_FLOW_ITEM_TYPE_ETH:
   14219                 :          0 :                 flow_dv_translate_item_eth(key, items, tunnel,
   14220                 :            :                                            wks->group, key_type);
   14221         [ #  # ]:          0 :                 wks->priority = wks->action_flags &
   14222                 :          0 :                                 MLX5_FLOW_ACTION_DEFAULT_MISS &&
   14223         [ #  # ]:          0 :                                 !wks->external ?
   14224                 :            :                                 MLX5_PRIORITY_MAP_L3 :
   14225                 :            :                                 MLX5_PRIORITY_MAP_L2;
   14226         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
   14227                 :            :                                      MLX5_FLOW_LAYER_OUTER_L2;
   14228                 :            :                 break;
   14229                 :          0 :         case RTE_FLOW_ITEM_TYPE_VLAN:
   14230                 :          0 :                 flow_dv_translate_item_vlan(key, items, tunnel, wks, key_type);
   14231                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L2;
   14232                 :            :                 last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
   14233         [ #  # ]:          0 :                                           MLX5_FLOW_LAYER_INNER_VLAN) :
   14234                 :            :                                          (MLX5_FLOW_LAYER_OUTER_L2 |
   14235                 :            :                                           MLX5_FLOW_LAYER_OUTER_VLAN);
   14236                 :            :                 break;
   14237                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:
   14238                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14239                 :            :                 l3_tunnel_detection =
   14240                 :            :                         mlx5_flow_tunnel_ip_check(items, next_protocol,
   14241                 :            :                                                   wks->item_flags,
   14242                 :            :                                                   &l3_tunnel_flag);
   14243                 :            :                 if (l3_tunnel_detection == l3_tunnel_inner) {
   14244                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14245                 :            :                         tunnel = 1;
   14246                 :            :                 }
   14247                 :          0 :                 flow_dv_translate_item_ipv4(key, items, tunnel,
   14248                 :            :                                             wks->group, key_type);
   14249                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L3;
   14250         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
   14251                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV4;
   14252         [ #  # ]:          0 :                 if (l3_tunnel_detection == l3_tunnel_outer)
   14253                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14254                 :            :                 break;
   14255                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:
   14256                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14257                 :            :                 l3_tunnel_detection =
   14258                 :            :                         mlx5_flow_tunnel_ip_check(items, next_protocol,
   14259                 :            :                                                   wks->item_flags,
   14260                 :            :                                                   &l3_tunnel_flag);
   14261                 :            :                 if (l3_tunnel_detection == l3_tunnel_inner) {
   14262                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14263                 :            :                         tunnel = 1;
   14264                 :            :                 }
   14265                 :          0 :                 flow_dv_translate_item_ipv6(key, items, tunnel,
   14266                 :            :                                             wks->group, key_type);
   14267                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L3;
   14268         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
   14269                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV6;
   14270         [ #  # ]:          0 :                 if (l3_tunnel_detection == l3_tunnel_outer)
   14271                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14272                 :            :                 break;
   14273                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
   14274                 :          0 :                 flow_dv_translate_item_ipv6_frag_ext
   14275                 :            :                                         (key, items, tunnel, key_type);
   14276         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT :
   14277                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT;
   14278                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14279                 :            :                 break;
   14280                 :          0 :         case RTE_FLOW_ITEM_TYPE_TCP:
   14281                 :          0 :                 flow_dv_translate_item_tcp(key, items, tunnel, key_type);
   14282                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14283         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
   14284                 :            :                                      MLX5_FLOW_LAYER_OUTER_L4_TCP;
   14285                 :            :                 break;
   14286                 :          0 :         case RTE_FLOW_ITEM_TYPE_UDP:
   14287                 :          0 :                 flow_dv_translate_item_udp(key, items, tunnel, wks, key_type);
   14288                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14289         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
   14290                 :            :                                      MLX5_FLOW_LAYER_OUTER_L4_UDP;
   14291                 :            :                 break;
   14292                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE:
   14293         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14294                 :          0 :                 wks->tunnel_item = items;
   14295                 :          0 :                 wks->gre_item = items;
   14296                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14297                 :          0 :                 break;
   14298                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_KEY:
   14299                 :          0 :                 flow_dv_translate_item_gre_key(key, items, key_type);
   14300                 :            :                 last_item = MLX5_FLOW_LAYER_GRE_KEY;
   14301                 :          0 :                 break;
   14302                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
   14303         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14304                 :          0 :                 wks->tunnel_item = items;
   14305                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14306                 :          0 :                 break;
   14307                 :          0 :         case RTE_FLOW_ITEM_TYPE_NVGRE:
   14308         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14309                 :          0 :                 wks->tunnel_item = items;
   14310                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14311                 :          0 :                 break;
   14312                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN:
   14313                 :          0 :                 flow_dv_translate_item_vxlan(dev, wks->attr, key,
   14314                 :            :                                              items, tunnel, wks, key_type);
   14315         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14316                 :            :                 last_item = MLX5_FLOW_LAYER_VXLAN;
   14317                 :          0 :                 break;
   14318                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
   14319         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14320                 :          0 :                 wks->tunnel_item = items;
   14321                 :            :                 last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
   14322                 :          0 :                 break;
   14323                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE:
   14324         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14325                 :          0 :                 wks->tunnel_item = items;
   14326                 :            :                 last_item = MLX5_FLOW_LAYER_GENEVE;
   14327                 :          0 :                 break;
   14328                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
   14329                 :          0 :                 ret = flow_dv_translate_item_geneve_opt
   14330                 :            :                                 (dev, key, items, key_type, error);
   14331         [ #  # ]:          0 :                 if (ret)
   14332                 :          0 :                         return rte_flow_error_set(error, -ret,
   14333                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14334                 :            :                                 "cannot create GENEVE TLV option");
   14335                 :          0 :                 wks->geneve_tlv_option = 1;
   14336                 :            :                 last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
   14337                 :          0 :                 break;
   14338                 :          0 :         case RTE_FLOW_ITEM_TYPE_MPLS:
   14339                 :          0 :                 flow_dv_translate_item_mpls(key, items, last_item,
   14340                 :            :                                             tunnel, key_type);
   14341         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14342                 :            :                 last_item = MLX5_FLOW_LAYER_MPLS;
   14343                 :          0 :                 break;
   14344                 :          0 :         case RTE_FLOW_ITEM_TYPE_MARK:
   14345                 :          0 :                 flow_dv_translate_item_mark(dev, key, items, key_type);
   14346                 :            :                 last_item = MLX5_FLOW_ITEM_MARK;
   14347                 :          0 :                 break;
   14348                 :          0 :         case RTE_FLOW_ITEM_TYPE_META:
   14349                 :          0 :                 flow_dv_translate_item_meta
   14350                 :            :                                 (dev, key, wks->attr, items, key_type);
   14351                 :            :                 last_item = MLX5_FLOW_ITEM_METADATA;
   14352                 :          0 :                 break;
   14353                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP:
   14354                 :          0 :                 flow_dv_translate_item_icmp(key, items, tunnel, key_type);
   14355                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14356                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP;
   14357                 :          0 :                 break;
   14358                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP6:
   14359                 :          0 :                 flow_dv_translate_item_icmp6(key, items, tunnel, key_type);
   14360                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14361                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP6;
   14362                 :          0 :                 break;
   14363                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
   14364                 :            :         case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
   14365                 :          0 :                 flow_dv_translate_item_icmp6_echo(key, items, tunnel, key_type);
   14366                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14367                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP6;
   14368                 :          0 :                 break;
   14369                 :          0 :         case RTE_FLOW_ITEM_TYPE_TAG:
   14370                 :          0 :                 flow_dv_translate_item_tag(dev, key, items, key_type);
   14371                 :            :                 last_item = MLX5_FLOW_ITEM_TAG;
   14372                 :          0 :                 break;
   14373                 :          0 :         case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
   14374                 :          0 :                 flow_dv_translate_mlx5_item_tag(dev, key, items, key_type);
   14375                 :            :                 last_item = MLX5_FLOW_ITEM_TAG;
   14376                 :          0 :                 break;
   14377                 :          0 :         case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
   14378                 :          0 :                 ret = flow_dv_translate_item_tx_queue(dev, key, items, key_type);
   14379         [ #  # ]:          0 :                 if (ret)
   14380                 :          0 :                         return rte_flow_error_set(error, -ret,
   14381                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14382                 :            :                                 "invalid tx_queue item");
   14383                 :            :                 last_item = MLX5_FLOW_ITEM_SQ;
   14384                 :            :                 break;
   14385                 :          0 :         case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   14386                 :          0 :                 flow_dv_translate_item_sq(key, items, key_type);
   14387                 :            :                 last_item = MLX5_FLOW_ITEM_SQ;
   14388                 :          0 :                 break;
   14389                 :          0 :         case RTE_FLOW_ITEM_TYPE_GTP:
   14390                 :          0 :                 flow_dv_translate_item_gtp(key, items, tunnel, key_type);
   14391         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14392                 :            :                 last_item = MLX5_FLOW_LAYER_GTP;
   14393                 :          0 :                 break;
   14394                 :          0 :         case RTE_FLOW_ITEM_TYPE_GTP_PSC:
   14395                 :          0 :                 ret = flow_dv_translate_item_gtp_psc(key, items, key_type);
   14396         [ #  # ]:          0 :                 if (ret)
   14397                 :          0 :                         return rte_flow_error_set(error, -ret,
   14398                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14399                 :            :                                 "cannot create GTP PSC item");
   14400                 :            :                 last_item = MLX5_FLOW_LAYER_GTP_PSC;
   14401                 :            :                 break;
   14402                 :          0 :         case RTE_FLOW_ITEM_TYPE_ECPRI:
   14403         [ #  # ]:          0 :                 if (!mlx5_flex_parser_ecpri_exist(dev)) {
   14404                 :            :                         /* Create it only the first time to be used. */
   14405                 :          0 :                         ret = mlx5_flex_parser_ecpri_alloc(dev);
   14406         [ #  # ]:          0 :                         if (ret)
   14407                 :          0 :                                 return rte_flow_error_set
   14408                 :            :                                         (error, -ret,
   14409                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM,
   14410                 :            :                                         NULL,
   14411                 :            :                                         "cannot create eCPRI parser");
   14412                 :            :                 }
   14413                 :          0 :                 flow_dv_translate_item_ecpri
   14414                 :            :                                 (dev, key, items, last_item, key_type);
   14415                 :            :                 /* No other protocol should follow eCPRI layer. */
   14416                 :            :                 last_item = MLX5_FLOW_LAYER_ECPRI;
   14417                 :          0 :                 break;
   14418                 :          0 :         case RTE_FLOW_ITEM_TYPE_METER_COLOR:
   14419                 :          0 :                 flow_dv_translate_item_meter_color(dev, key, items, key_type);
   14420                 :            :                 last_item = MLX5_FLOW_ITEM_METER_COLOR;
   14421                 :          0 :                 break;
   14422         [ #  # ]:          0 :         case RTE_FLOW_ITEM_TYPE_INTEGRITY:
   14423                 :            :                 last_item = flow_dv_translate_item_integrity(items,
   14424                 :            :                                                              wks, key_type);
   14425                 :          0 :                 break;
   14426                 :          0 :         case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
   14427                 :          0 :                 flow_dv_translate_item_aggr_affinity(key, items, key_type);
   14428                 :            :                 last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
   14429                 :          0 :                 break;
   14430                 :          0 :         case RTE_FLOW_ITEM_TYPE_IB_BTH:
   14431                 :          0 :                 flow_dv_translate_item_ib_bth(key, items, tunnel, key_type);
   14432                 :            :                 last_item = MLX5_FLOW_ITEM_IB_BTH;
   14433                 :          0 :                 break;
   14434                 :          0 :         case RTE_FLOW_ITEM_TYPE_NSH:
   14435                 :            :                 last_item = MLX5_FLOW_ITEM_NSH;
   14436                 :          0 :                 break;
   14437                 :            :         default:
   14438                 :            :                 break;
   14439                 :            :         }
   14440                 :          0 :         wks->item_flags |= last_item;
   14441                 :          0 :         wks->last_item = last_item;
   14442                 :          0 :         wks->next_protocol = next_protocol;
   14443                 :          0 :         return 0;
   14444                 :            : }
   14445                 :            : 
   14446                 :            : /**
   14447                 :            :  * Fill the flow matcher with DV spec for items supported in non template mode.
   14448                 :            :  *
   14449                 :            :  * @param[in] dev
   14450                 :            :  *   Pointer to rte_eth_dev structure.
   14451                 :            :  * @param[in] items
   14452                 :            :  *   Pointer to the list of items.
   14453                 :            :  * @param[in] wks
   14454                 :            :  *   Pointer to the matcher workspace.
   14455                 :            :  * @param[in] key
   14456                 :            :  *   Pointer to the flow matcher key.
   14457                 :            :  * @param[in] key_type
   14458                 :            :  *   Key type.
   14459                 :            :  * @param[out] error
   14460                 :            :  *   Pointer to the error structure.
   14461                 :            :  *
   14462                 :            :  * @return
   14463                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14464                 :            :  */
   14465                 :            : static int
   14466                 :          0 : flow_dv_translate_items_nta(struct rte_eth_dev *dev,
   14467                 :            :                         const struct rte_flow_item *items,
   14468                 :            :                         struct mlx5_dv_matcher_workspace *wks,
   14469                 :            :                         void *key, uint32_t key_type,
   14470                 :            :                         struct rte_flow_error *error)
   14471                 :            : {
   14472                 :            :         int item_type;
   14473                 :            :         int ret = 0;
   14474                 :            :         int tunnel;
   14475                 :            :         /* Dummy structure to enable the key calculation for flex item. */
   14476                 :            :         struct mlx5_flow_dv_match_params flex_item_key;
   14477                 :            : 
   14478                 :          0 :         tunnel = !!(wks->item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14479                 :          0 :         item_type = items->type;
   14480      [ #  #  # ]:          0 :         switch (item_type) {
   14481                 :          0 :         case RTE_FLOW_ITEM_TYPE_CONNTRACK:
   14482                 :          0 :                 flow_dv_translate_item_aso_ct(dev, key, NULL, items);
   14483                 :          0 :                 wks->last_item = MLX5_FLOW_LAYER_ASO_CT;
   14484                 :          0 :                 break;
   14485                 :            :         /* TODO: remove once flex item translation is added to flow_dv_translate_items. */
   14486                 :          0 :         case RTE_FLOW_ITEM_TYPE_FLEX:
   14487                 :          0 :                 mlx5_flex_flow_translate_item(dev, key, flex_item_key.buf, items, tunnel != 0);
   14488         [ #  # ]:          0 :                 wks->last_item = tunnel ? MLX5_FLOW_ITEM_INNER_FLEX : MLX5_FLOW_ITEM_OUTER_FLEX;
   14489                 :          0 :                 break;
   14490                 :          0 :         default:
   14491                 :          0 :                 ret = flow_dv_translate_items(dev, items, wks, key, key_type,  error);
   14492         [ #  # ]:          0 :                 if (ret)
   14493                 :            :                         return ret;
   14494                 :            :                 break;
   14495                 :            :         }
   14496                 :          0 :         wks->item_flags |= wks->last_item;
   14497                 :          0 :         return 0;
   14498                 :            : }
   14499                 :            : 
   14500                 :            : /**
   14501                 :            :  * Fill the HW steering flow with DV spec.
   14502                 :            :  *
   14503                 :            :  * @param[in] items
   14504                 :            :  *   Pointer to the list of items.
   14505                 :            :  * @param[in] attr
   14506                 :            :  *   Pointer to the flow attributes.
   14507                 :            :  * @param[in] key
   14508                 :            :  *   Pointer to the flow matcher key.
   14509                 :            :  * @param[in] key_type
   14510                 :            :  *   Key type.
   14511                 :            :  * @param[in, out] item_flags
   14512                 :            :  *   Pointer to the flow item flags.
   14513                 :            :  * @param[in, out] nt_flow
   14514                 :            :  *   Non template flow.
   14515                 :            :  * @param[out] error
   14516                 :            :  *   Pointer to the error structure.
   14517                 :            :  *
   14518                 :            :  * @return
   14519                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14520                 :            :  */
   14521                 :            : int
   14522                 :          0 : __flow_dv_translate_items_hws(const struct rte_flow_item *items,
   14523                 :            :                             struct mlx5_flow_attr *attr, void *key,
   14524                 :            :                             uint32_t key_type, uint64_t *item_flags,
   14525                 :            :                             uint8_t *match_criteria,
   14526                 :            :                             bool nt_flow,
   14527                 :            :                             struct rte_flow_error *error)
   14528                 :            : {
   14529                 :          0 :         struct mlx5_flow_workspace *flow_wks = mlx5_flow_push_thread_workspace();
   14530                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { .level = attr->rss_level };
   14531                 :          0 :         struct rte_flow_attr rattr = {
   14532                 :          0 :                 .group = attr->group,
   14533                 :          0 :                 .priority = attr->priority,
   14534                 :          0 :                 .ingress = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_NIC_RX),
   14535                 :          0 :                 .egress = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_NIC_TX),
   14536                 :          0 :                 .transfer = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_FDB),
   14537                 :            :         };
   14538                 :          0 :         struct mlx5_dv_matcher_workspace wks = {
   14539                 :          0 :                 .action_flags = attr->act_flags,
   14540         [ #  # ]:          0 :                 .item_flags = item_flags ? *item_flags : 0,
   14541                 :            :                 .external = 0,
   14542                 :            :                 .next_protocol = 0xff,
   14543                 :            :                 .attr = &rattr,
   14544                 :            :                 .rss_desc = &rss_desc,
   14545                 :            :                 .group = attr->group,
   14546                 :            :         };
   14547                 :            :         int ret = 0;
   14548                 :            : 
   14549                 :            :         RTE_SET_USED(flow_wks);
   14550         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
   14551                 :            :                 if (!mlx5_flow_os_item_supported(items->type)) {
   14552                 :            :                         ret = rte_flow_error_set(error, ENOTSUP,
   14553                 :            :                                                  RTE_FLOW_ERROR_TYPE_ITEM,
   14554                 :            :                                                  NULL, "item not supported");
   14555                 :            :                         goto exit;
   14556                 :            :                 }
   14557                 :            :                 /* Non template flow. */
   14558         [ #  # ]:          0 :                 if (nt_flow) {
   14559                 :          0 :                         ret = flow_dv_translate_items_nta(&rte_eth_devices[attr->port_id],
   14560                 :            :                                                           items, &wks, key, key_type,  NULL);
   14561         [ #  # ]:          0 :                         if (ret)
   14562                 :          0 :                                 goto exit;
   14563                 :            :                 } else {
   14564                 :          0 :                         ret = flow_dv_translate_items(&rte_eth_devices[attr->port_id],
   14565                 :            :                                                       items, &wks, key, key_type,  NULL);
   14566         [ #  # ]:          0 :                         if (ret)
   14567                 :          0 :                                 goto exit;
   14568                 :            :                 }
   14569                 :            :         }
   14570         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
   14571                 :          0 :                 flow_dv_translate_item_integrity_post(key,
   14572                 :            :                                                       wks.integrity_items,
   14573                 :            :                                                       wks.item_flags,
   14574                 :            :                                                       key_type);
   14575                 :            :         }
   14576         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_LAYER_VXLAN_GPE) {
   14577                 :          0 :                 flow_dv_translate_item_vxlan_gpe(key,
   14578                 :            :                                                  wks.tunnel_item,
   14579                 :            :                                                  wks.item_flags,
   14580                 :            :                                                  key_type);
   14581         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GENEVE) {
   14582                 :          0 :                 flow_dv_translate_item_geneve(key,
   14583                 :            :                                               wks.tunnel_item,
   14584                 :            :                                               wks.item_flags,
   14585                 :            :                                               key_type);
   14586         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GRE) {
   14587         [ #  # ]:          0 :                 if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE) {
   14588                 :          0 :                         flow_dv_translate_item_gre(key,
   14589                 :            :                                                    wks.tunnel_item,
   14590                 :            :                                                    wks.item_flags,
   14591                 :            :                                                    key_type);
   14592         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION) {
   14593                 :          0 :                         flow_dv_translate_item_gre_option(key,
   14594                 :            :                                                           wks.tunnel_item,
   14595                 :            :                                                           wks.gre_item,
   14596                 :            :                                                           wks.item_flags,
   14597                 :            :                                                           key_type);
   14598         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
   14599                 :          0 :                         flow_dv_translate_item_nvgre(key,
   14600                 :            :                                                      wks.tunnel_item,
   14601                 :            :                                                      wks.item_flags,
   14602                 :            :                                                      key_type);
   14603                 :            :                 } else {
   14604                 :            :                         MLX5_ASSERT(false);
   14605                 :            :                 }
   14606                 :            :         }
   14607                 :            : 
   14608         [ #  # ]:          0 :         if (match_criteria)
   14609                 :          0 :                 *match_criteria = flow_dv_matcher_enable(key);
   14610         [ #  # ]:          0 :         if (item_flags)
   14611                 :          0 :                 *item_flags = wks.item_flags;
   14612                 :          0 : exit:
   14613                 :          0 :         mlx5_flow_pop_thread_workspace();
   14614                 :          0 :         return ret;
   14615                 :            : }
   14616                 :            : 
   14617                 :            : /**
   14618                 :            :  * Fill the HW steering flow with DV spec.
   14619                 :            :  * This function assumes given flow is created from template API.
   14620                 :            :  *
   14621                 :            :  * @param[in] items
   14622                 :            :  *   Pointer to the list of items.
   14623                 :            :  * @param[in] attr
   14624                 :            :  *   Pointer to the flow attributes.
   14625                 :            :  * @param[in] key
   14626                 :            :  *   Pointer to the flow matcher key.
   14627                 :            :  * @param[in] key_type
   14628                 :            :  *   Key type.
   14629                 :            :  * @param[in, out] item_flags
   14630                 :            :  *   Pointer to the flow item flags.
   14631                 :            :  * @param[out] error
   14632                 :            :  *   Pointer to the error structure.
   14633                 :            :  *
   14634                 :            :  * @return
   14635                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14636                 :            :  */
   14637                 :            : int
   14638                 :          0 : flow_dv_translate_items_hws(const struct rte_flow_item *items,
   14639                 :            :                             struct mlx5_flow_attr *attr, void *key,
   14640                 :            :                             uint32_t key_type, uint64_t *item_flags,
   14641                 :            :                             uint8_t *match_criteria,
   14642                 :            :                             struct rte_flow_error *error)
   14643                 :            : {
   14644                 :          0 :         return __flow_dv_translate_items_hws(items, attr, key, key_type, item_flags, match_criteria,
   14645                 :            :                                              false, error);
   14646                 :            : }
   14647                 :            : 
   14648                 :            : /**
   14649                 :            :  * Fill the SW steering flow with DV spec.
   14650                 :            :  *
   14651                 :            :  * @param[in] dev
   14652                 :            :  *   Pointer to rte_eth_dev structure.
   14653                 :            :  * @param[in, out] dev_flow
   14654                 :            :  *   Pointer to the sub flow.
   14655                 :            :  * @param[in] attr
   14656                 :            :  *   Pointer to the flow attributes.
   14657                 :            :  * @param[in] items
   14658                 :            :  *   Pointer to the list of items.
   14659                 :            :  * @param[in, out] matcher
   14660                 :            :  *   Pointer to the flow matcher.
   14661                 :            :  * @param[out] error
   14662                 :            :  *   Pointer to the error structure.
   14663                 :            :  *
   14664                 :            :  * @return
   14665                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14666                 :            :  */
   14667                 :            : static int
   14668                 :          0 : flow_dv_translate_items_sws(struct rte_eth_dev *dev,
   14669                 :            :                             struct mlx5_flow *dev_flow,
   14670                 :            :                             const struct rte_flow_attr *attr,
   14671                 :            :                             const struct rte_flow_item *items,
   14672                 :            :                             struct mlx5_flow_dv_matcher *matcher,
   14673                 :            :                             struct rte_flow_error *error)
   14674                 :            : {
   14675                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14676                 :          0 :         void *match_mask = matcher->mask.buf;
   14677                 :          0 :         void *match_value = dev_flow->dv.value.buf;
   14678                 :          0 :         struct mlx5_dv_matcher_workspace wks = {
   14679                 :          0 :                 .action_flags = dev_flow->act_flags,
   14680                 :            :                 .item_flags = 0,
   14681                 :          0 :                 .external = dev_flow->external,
   14682                 :            :                 .next_protocol = 0xff,
   14683                 :          0 :                 .group = dev_flow->dv.group,
   14684                 :            :                 .attr = attr,
   14685                 :          0 :                 .rss_desc = &((struct mlx5_flow_workspace *)
   14686                 :            :                              mlx5_flow_get_thread_workspace())->rss_desc,
   14687                 :            :         };
   14688                 :          0 :         struct mlx5_dv_matcher_workspace wks_m = wks;
   14689                 :            :         int item_type;
   14690                 :            :         int ret = 0;
   14691                 :            :         int tunnel;
   14692                 :            : 
   14693         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
   14694                 :          0 :                 if (!mlx5_flow_os_item_supported(items->type))
   14695                 :            :                         return rte_flow_error_set(error, ENOTSUP,
   14696                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
   14697                 :            :                                                   NULL, "item not supported");
   14698                 :          0 :                 tunnel = !!(wks.item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14699                 :            :                 item_type = items->type;
   14700   [ #  #  #  #  :          0 :                 switch (item_type) {
                      # ]
   14701                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
   14702                 :          0 :                         flow_dv_translate_item_aso_ct(dev, match_mask,
   14703                 :            :                                                       match_value, items);
   14704                 :          0 :                         wks.last_item = MLX5_FLOW_LAYER_ASO_CT;
   14705                 :          0 :                         break;
   14706                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
   14707                 :          0 :                         flow_dv_translate_item_flex(dev, match_mask,
   14708                 :            :                                                     match_value, items,
   14709                 :            :                                                     dev_flow, tunnel != 0);
   14710         [ #  # ]:          0 :                         wks.last_item = tunnel ? MLX5_FLOW_ITEM_INNER_FLEX :
   14711                 :            :                                                  MLX5_FLOW_ITEM_OUTER_FLEX;
   14712                 :          0 :                         break;
   14713                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
   14714                 :          0 :                         ret = flow_dv_translate_item_tx_queue(dev, match_value, items,
   14715                 :            :                                                               MLX5_SET_MATCHER_SW_V);
   14716         [ #  # ]:          0 :                         if (ret)
   14717                 :          0 :                                 return rte_flow_error_set(error, -ret,
   14718                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14719                 :            :                                         "invalid tx_queue item spec");
   14720                 :          0 :                         ret = flow_dv_translate_item_tx_queue(dev, match_mask, items,
   14721                 :            :                                                               MLX5_SET_MATCHER_SW_M);
   14722         [ #  # ]:          0 :                         if (ret)
   14723                 :          0 :                                 return rte_flow_error_set(error, -ret,
   14724                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14725                 :            :                                         "invalid tx_queue item mask");
   14726                 :            :                         break;
   14727                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   14728                 :          0 :                         flow_dv_translate_item_sq(match_value, items,
   14729                 :            :                                                   MLX5_SET_MATCHER_SW_V);
   14730                 :          0 :                         flow_dv_translate_item_sq(match_mask, items,
   14731                 :            :                                                   MLX5_SET_MATCHER_SW_M);
   14732                 :          0 :                         break;
   14733                 :          0 :                 default:
   14734                 :          0 :                         ret = flow_dv_translate_items(dev, items, &wks_m,
   14735                 :            :                                 match_mask, MLX5_SET_MATCHER_SW_M, error);
   14736         [ #  # ]:          0 :                         if (ret)
   14737                 :          0 :                                 return ret;
   14738                 :          0 :                         ret = flow_dv_translate_items(dev, items, &wks,
   14739                 :            :                                 match_value, MLX5_SET_MATCHER_SW_V, error);
   14740         [ #  # ]:          0 :                         if (ret)
   14741                 :          0 :                                 return ret;
   14742                 :            :                         break;
   14743                 :            :                 }
   14744                 :          0 :                 wks.item_flags |= wks.last_item;
   14745                 :            :         }
   14746                 :            :         /*
   14747                 :            :          * When E-Switch mode is enabled, we have two cases where we need to
   14748                 :            :          * set the source port manually.
   14749                 :            :          * The first one, is in case of NIC ingress steering rule, and the
   14750                 :            :          * second is E-Switch rule where no port_id item was found.
   14751                 :            :          * In both cases the source port is set according the current port
   14752                 :            :          * in use.
   14753                 :            :          */
   14754                 :          0 :         if (!(wks.item_flags & MLX5_FLOW_ITEM_PORT_ID) &&
   14755         [ #  # ]:          0 :             !(wks.item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT) &&
   14756                 :          0 :             !(wks.item_flags & MLX5_FLOW_ITEM_PORT_REPRESENTOR) &&
   14757         [ #  # ]:          0 :             priv->sh->esw_mode &&
   14758         [ #  # ]:          0 :             !attr->egress &&
   14759         [ #  # ]:          0 :             attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP) {
   14760         [ #  # ]:          0 :                 if (flow_dv_translate_item_port_id_all(dev, match_mask,
   14761                 :            :                                                    match_value, NULL, attr))
   14762                 :          0 :                         return -rte_errno;
   14763                 :            :         }
   14764         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
   14765                 :          0 :                 flow_dv_translate_item_integrity_post(match_mask,
   14766                 :            :                                                       wks_m.integrity_items,
   14767                 :            :                                                       wks_m.item_flags,
   14768                 :            :                                                       MLX5_SET_MATCHER_SW_M);
   14769                 :          0 :                 flow_dv_translate_item_integrity_post(match_value,
   14770                 :            :                                                       wks.integrity_items,
   14771                 :            :                                                       wks.item_flags,
   14772                 :            :                                                       MLX5_SET_MATCHER_SW_V);
   14773                 :            :         }
   14774         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_LAYER_VXLAN_GPE) {
   14775                 :          0 :                 flow_dv_translate_item_vxlan_gpe(match_mask,
   14776                 :            :                                                  wks.tunnel_item,
   14777                 :            :                                                  wks.item_flags,
   14778                 :            :                                                  MLX5_SET_MATCHER_SW_M);
   14779                 :          0 :                 flow_dv_translate_item_vxlan_gpe(match_value,
   14780                 :            :                                                  wks.tunnel_item,
   14781                 :            :                                                  wks.item_flags,
   14782                 :            :                                                  MLX5_SET_MATCHER_SW_V);
   14783         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GENEVE) {
   14784                 :          0 :                 flow_dv_translate_item_geneve(match_mask,
   14785                 :            :                                               wks.tunnel_item,
   14786                 :            :                                               wks.item_flags,
   14787                 :            :                                               MLX5_SET_MATCHER_SW_M);
   14788                 :          0 :                 flow_dv_translate_item_geneve(match_value,
   14789                 :            :                                               wks.tunnel_item,
   14790                 :            :                                               wks.item_flags,
   14791                 :            :                                               MLX5_SET_MATCHER_SW_V);
   14792         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GRE) {
   14793         [ #  # ]:          0 :                 if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE) {
   14794                 :          0 :                         flow_dv_translate_item_gre(match_mask,
   14795                 :            :                                                    wks.tunnel_item,
   14796                 :            :                                                    wks.item_flags,
   14797                 :            :                                                    MLX5_SET_MATCHER_SW_M);
   14798                 :          0 :                         flow_dv_translate_item_gre(match_value,
   14799                 :            :                                                    wks.tunnel_item,
   14800                 :            :                                                    wks.item_flags,
   14801                 :            :                                                    MLX5_SET_MATCHER_SW_V);
   14802         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
   14803                 :          0 :                         flow_dv_translate_item_nvgre(match_mask,
   14804                 :            :                                                      wks.tunnel_item,
   14805                 :            :                                                      wks.item_flags,
   14806                 :            :                                                      MLX5_SET_MATCHER_SW_M);
   14807                 :          0 :                         flow_dv_translate_item_nvgre(match_value,
   14808                 :            :                                                      wks.tunnel_item,
   14809                 :            :                                                      wks.item_flags,
   14810                 :            :                                                      MLX5_SET_MATCHER_SW_V);
   14811         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION) {
   14812                 :          0 :                         flow_dv_translate_item_gre_option(match_mask,
   14813                 :            :                                                           wks.tunnel_item,
   14814                 :            :                                                           wks.gre_item,
   14815                 :            :                                                           wks.item_flags,
   14816                 :            :                                                           MLX5_SET_MATCHER_SW_M);
   14817                 :          0 :                         flow_dv_translate_item_gre_option(match_value,
   14818                 :            :                                                           wks.tunnel_item,
   14819                 :            :                                                           wks.gre_item,
   14820                 :            :                                                           wks.item_flags,
   14821                 :            :                                                           MLX5_SET_MATCHER_SW_V);
   14822                 :            :                 } else {
   14823                 :            :                         MLX5_ASSERT(false);
   14824                 :            :                 }
   14825                 :            :         }
   14826                 :          0 :         dev_flow->handle->vf_vlan.tag = wks.vlan_tag;
   14827                 :          0 :         matcher->priority = wks.priority;
   14828                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
   14829                 :            :         MLX5_ASSERT(!flow_dv_check_valid_spec(match_mask, match_value));
   14830                 :            : #endif
   14831                 :            :         /*
   14832                 :            :          * Layers may be already initialized from prefix flow if this dev_flow
   14833                 :            :          * is the suffix flow.
   14834                 :            :          */
   14835                 :          0 :         dev_flow->handle->layers |= wks.item_flags;
   14836                 :            :         /*
   14837                 :            :          * Update geneve_tlv_option flag only it is set in workspace.
   14838                 :            :          * Avoid be overwritten by other sub mlx5_flows.
   14839                 :            :          */
   14840         [ #  # ]:          0 :         if (wks.geneve_tlv_option)
   14841                 :          0 :                 dev_flow->flow->geneve_tlv_option += wks.geneve_tlv_option;
   14842                 :            :         return 0;
   14843                 :            : }
   14844                 :            : 
   14845                 :            : /**
   14846                 :            :  * Fill the flow with DV spec, lock free
   14847                 :            :  * (mutex should be acquired by caller).
   14848                 :            :  *
   14849                 :            :  * @param[in] dev
   14850                 :            :  *   Pointer to rte_eth_dev structure.
   14851                 :            :  * @param[in, out] dev_flow
   14852                 :            :  *   Pointer to the sub flow.
   14853                 :            :  * @param[in] attr
   14854                 :            :  *   Pointer to the flow attributes.
   14855                 :            :  * @param[in] items
   14856                 :            :  *   Pointer to the list of items.
   14857                 :            :  * @param[in] actions
   14858                 :            :  *   Pointer to the list of actions.
   14859                 :            :  * @param[out] error
   14860                 :            :  *   Pointer to the error structure.
   14861                 :            :  *
   14862                 :            :  * @return
   14863                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14864                 :            :  */
   14865                 :            : static int
   14866                 :          0 : flow_dv_translate(struct rte_eth_dev *dev,
   14867                 :            :                   struct mlx5_flow *dev_flow,
   14868                 :            :                   const struct rte_flow_attr *attr,
   14869                 :            :                   const struct rte_flow_item items[],
   14870                 :            :                   const struct rte_flow_action actions[],
   14871                 :            :                   struct rte_flow_error *error)
   14872                 :            : {
   14873                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14874                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
   14875                 :          0 :         struct rte_flow *flow = dev_flow->flow;
   14876                 :          0 :         struct mlx5_flow_handle *handle = dev_flow->handle;
   14877                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   14878                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   14879                 :            :         uint64_t action_flags = 0;
   14880                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   14881                 :            :                 .mask = {
   14882                 :            :                         .size = sizeof(matcher.mask.buf),
   14883                 :            :                 },
   14884                 :            :         };
   14885                 :            :         int actions_n = 0;
   14886                 :            :         bool actions_end = false;
   14887                 :            :         union {
   14888                 :            :                 struct mlx5_flow_dv_modify_hdr_resource res;
   14889                 :            :                 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   14890                 :            :                             sizeof(struct mlx5_modification_cmd) *
   14891                 :            :                             (MLX5_MAX_MODIFY_NUM + 1)];
   14892                 :            :         } mhdr_dummy;
   14893                 :            :         struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
   14894                 :            :         const struct rte_flow_action_count *count = NULL;
   14895                 :            :         const struct rte_flow_action_age *non_shared_age = NULL;
   14896                 :          0 :         union flow_dv_attr flow_attr = { .attr = 0 };
   14897                 :            :         uint32_t tag_be;
   14898                 :            :         union mlx5_flow_tbl_key tbl_key;
   14899                 :            :         uint32_t modify_action_position = UINT32_MAX;
   14900                 :          0 :         struct rte_vlan_hdr vlan = { 0 };
   14901                 :            :         struct mlx5_flow_dv_dest_array_resource mdest_res;
   14902                 :            :         struct mlx5_flow_dv_sample_resource sample_res;
   14903                 :          0 :         void *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
   14904                 :            :         const struct rte_flow_action_sample *sample = NULL;
   14905                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   14906                 :            :         uint32_t sample_act_pos = UINT32_MAX;
   14907                 :            :         uint32_t age_act_pos = UINT32_MAX;
   14908                 :            :         uint32_t ipv6_tc_off = 0;
   14909                 :          0 :         uint32_t num_of_dest = 0;
   14910                 :            :         int tmp_actions_n = 0;
   14911                 :            :         uint32_t table;
   14912                 :            :         int ret = 0;
   14913                 :            :         const struct mlx5_flow_tunnel *tunnel = NULL;
   14914                 :          0 :         struct flow_grp_info grp_info = {
   14915                 :          0 :                 .external = !!dev_flow->external,
   14916                 :          0 :                 .transfer = !!attr->transfer,
   14917                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
   14918                 :          0 :                 .skip_scale = dev_flow->skip_scale &
   14919                 :            :                         (1 << MLX5_SCALE_FLOW_GROUP_BIT),
   14920                 :            :                 .std_tbl_fix = true,
   14921                 :            :         };
   14922                 :            : 
   14923         [ #  # ]:          0 :         if (!wks)
   14924                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   14925                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   14926                 :            :                                           NULL,
   14927                 :            :                                           "failed to push flow workspace");
   14928         [ #  # ]:          0 :         rss_desc = &wks->rss_desc;
   14929                 :            :         memset(&mdest_res, 0, sizeof(struct mlx5_flow_dv_dest_array_resource));
   14930                 :            :         memset(&sample_res, 0, sizeof(struct mlx5_flow_dv_sample_resource));
   14931         [ #  # ]:          0 :         mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   14932                 :            :                                            MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   14933                 :            :         /* update normal path action resource into last index of array */
   14934                 :            :         sample_act = &mdest_res.sample_act[MLX5_MAX_DEST_NUM - 1];
   14935         [ #  # ]:          0 :         if (is_tunnel_offload_active(dev)) {
   14936         [ #  # ]:          0 :                 if (dev_flow->tunnel) {
   14937         [ #  # ]:          0 :                         RTE_VERIFY(dev_flow->tof_type ==
   14938                 :            :                                    MLX5_TUNNEL_OFFLOAD_MISS_RULE);
   14939                 :            :                         tunnel = dev_flow->tunnel;
   14940                 :            :                 } else {
   14941                 :          0 :                         tunnel = mlx5_get_tof(items, actions,
   14942                 :            :                                               &dev_flow->tof_type);
   14943                 :          0 :                         dev_flow->tunnel = tunnel;
   14944                 :            :                 }
   14945         [ #  # ]:          0 :                 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
   14946                 :            :                                         (dev, attr, tunnel, dev_flow->tof_type);
   14947                 :            :         }
   14948                 :          0 :         mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   14949                 :            :                                            MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   14950                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, attr->group, &table,
   14951                 :            :                                        &grp_info, error);
   14952         [ #  # ]:          0 :         if (ret)
   14953                 :            :                 return ret;
   14954                 :          0 :         dev_flow->dv.group = table;
   14955         [ #  # ]:          0 :         if (attr->transfer)
   14956                 :          0 :                 mhdr_res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
   14957                 :            :         /* number of actions must be set to 0 in case of dirty stack. */
   14958                 :          0 :         mhdr_res->actions_num = 0;
   14959         [ #  # ]:          0 :         if (is_flow_tunnel_match_rule(dev_flow->tof_type)) {
   14960                 :            :                 /*
   14961                 :            :                  * do not add decap action if match rule drops packet
   14962                 :            :                  * HW rejects rules with decap & drop
   14963                 :            :                  *
   14964                 :            :                  * if tunnel match rule was inserted before matching tunnel set
   14965                 :            :                  * rule flow table used in the match rule must be registered.
   14966                 :            :                  * current implementation handles that in the
   14967                 :            :                  * flow_dv_match_register() at the function end.
   14968                 :            :                  */
   14969                 :            :                 bool add_decap = true;
   14970                 :            :                 const struct rte_flow_action *ptr = actions;
   14971                 :            : 
   14972         [ #  # ]:          0 :                 for (; ptr->type != RTE_FLOW_ACTION_TYPE_END; ptr++) {
   14973         [ #  # ]:          0 :                         if (ptr->type == RTE_FLOW_ACTION_TYPE_DROP) {
   14974                 :            :                                 add_decap = false;
   14975                 :            :                                 break;
   14976                 :            :                         }
   14977                 :            :                 }
   14978         [ #  # ]:          0 :                 if (add_decap) {
   14979         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_decap(dev, dev_flow,
   14980                 :          0 :                                                            attr->transfer,
   14981                 :            :                                                            error))
   14982                 :          0 :                                 return -rte_errno;
   14983                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   14984                 :          0 :                                         dev_flow->dv.encap_decap->action;
   14985                 :            :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   14986                 :            :                 }
   14987                 :            :         }
   14988         [ #  # ]:          0 :         for (; !actions_end ; actions++) {
   14989                 :            :                 const struct rte_flow_action_queue *queue;
   14990                 :            :                 const struct rte_flow_action_rss *rss;
   14991                 :            :                 const struct rte_flow_action *action = actions;
   14992                 :            :                 const uint8_t *rss_key;
   14993                 :            :                 struct mlx5_flow_tbl_resource *tbl;
   14994                 :            :                 struct mlx5_aso_age_action *age_act;
   14995                 :            :                 struct mlx5_flow_counter *cnt_act;
   14996                 :          0 :                 uint32_t port_id = 0;
   14997                 :            :                 struct mlx5_flow_dv_port_id_action_resource port_id_resource;
   14998                 :          0 :                 int action_type = actions->type;
   14999                 :            :                 const struct rte_flow_action *found_action = NULL;
   15000                 :            :                 uint32_t jump_group = 0;
   15001                 :            :                 uint32_t owner_idx;
   15002                 :            :                 struct mlx5_aso_ct_action *ct;
   15003                 :            : 
   15004                 :            :                 if (!mlx5_flow_os_action_supported(action_type))
   15005                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   15006                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   15007                 :            :                                                   actions,
   15008                 :            :                                                   "action not supported");
   15009   [ #  #  #  #  :          0 :                 switch (action_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
   15010                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET:
   15011                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;
   15012                 :          0 :                         break;
   15013                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   15014                 :            :                         break;
   15015                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
   15016                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   15017         [ #  # ]:          0 :                         if (flow_dv_translate_action_port_id(dev, action,
   15018                 :            :                                                              &port_id, error))
   15019                 :          0 :                                 return -rte_errno;
   15020                 :          0 :                         port_id_resource.port_id = port_id;
   15021                 :            :                         MLX5_ASSERT(!handle->rix_port_id_action);
   15022         [ #  # ]:          0 :                         if (flow_dv_port_id_action_resource_register
   15023                 :            :                             (dev, &port_id_resource, dev_flow, error))
   15024                 :          0 :                                 return -rte_errno;
   15025                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15026                 :          0 :                                         dev_flow->dv.port_id_action->action;
   15027                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   15028                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_PORT_ID;
   15029                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   15030                 :          0 :                         num_of_dest++;
   15031                 :          0 :                         break;
   15032                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
   15033                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_FLAG;
   15034                 :          0 :                         wks->mark = 1;
   15035         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
   15036                 :          0 :                                 struct rte_flow_action_mark mark = {
   15037                 :            :                                         .id = MLX5_FLOW_MARK_DEFAULT,
   15038                 :            :                                 };
   15039                 :            : 
   15040         [ #  # ]:          0 :                                 if (flow_dv_convert_action_mark(dev, &mark,
   15041                 :            :                                                                 mhdr_res,
   15042                 :            :                                                                 error))
   15043                 :          0 :                                         return -rte_errno;
   15044                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
   15045                 :          0 :                                 break;
   15046                 :            :                         }
   15047                 :            :                         tag_be = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT);
   15048                 :            :                         /*
   15049                 :            :                          * Only one FLAG or MARK is supported per device flow
   15050                 :            :                          * right now. So the pointer to the tag resource must be
   15051                 :            :                          * zero before the register process.
   15052                 :            :                          */
   15053                 :            :                         MLX5_ASSERT(!handle->dvh.rix_tag);
   15054         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   15055                 :            :                                                           dev_flow, error))
   15056                 :          0 :                                 return -rte_errno;
   15057                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   15058                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15059                 :          0 :                                         dev_flow->dv.tag_resource->action;
   15060                 :          0 :                         break;
   15061                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
   15062                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
   15063                 :          0 :                         wks->mark = 1;
   15064         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
   15065                 :          0 :                                 const struct rte_flow_action_mark *mark =
   15066                 :            :                                         (const struct rte_flow_action_mark *)
   15067                 :            :                                                 actions->conf;
   15068                 :            : 
   15069         [ #  # ]:          0 :                                 if (flow_dv_convert_action_mark(dev, mark,
   15070                 :            :                                                                 mhdr_res,
   15071                 :            :                                                                 error))
   15072                 :          0 :                                         return -rte_errno;
   15073                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
   15074                 :          0 :                                 break;
   15075                 :            :                         }
   15076                 :            :                         /* Fall-through */
   15077                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
   15078                 :            :                         /* Legacy (non-extensive) MARK action. */
   15079                 :            :                         tag_be = mlx5_flow_mark_set
   15080                 :            :                               (((const struct rte_flow_action_mark *)
   15081         [ #  # ]:          0 :                                (actions->conf))->id);
   15082                 :            :                         MLX5_ASSERT(!handle->dvh.rix_tag);
   15083         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   15084                 :            :                                                           dev_flow, error))
   15085                 :          0 :                                 return -rte_errno;
   15086                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   15087                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15088                 :          0 :                                         dev_flow->dv.tag_resource->action;
   15089                 :          0 :                         break;
   15090                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_META:
   15091         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_meta
   15092                 :            :                                 (dev, mhdr_res, attr,
   15093                 :            :                                  (const struct rte_flow_action_set_meta *)
   15094                 :          0 :                                   actions->conf, error))
   15095                 :          0 :                                 return -rte_errno;
   15096                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_META;
   15097                 :          0 :                         break;
   15098                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
   15099         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_tag
   15100                 :            :                                 (dev, mhdr_res,
   15101                 :            :                                  (const struct rte_flow_action_set_tag *)
   15102                 :          0 :                                   actions->conf, error))
   15103                 :          0 :                                 return -rte_errno;
   15104                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15105                 :          0 :                         break;
   15106                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
   15107                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
   15108                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP;
   15109                 :          0 :                         break;
   15110                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   15111                 :          0 :                         queue = actions->conf;
   15112                 :          0 :                         rss_desc->queue_num = 1;
   15113                 :          0 :                         rss_desc->queue[0] = queue->index;
   15114                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
   15115                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
   15116                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_QUEUE;
   15117                 :          0 :                         num_of_dest++;
   15118                 :          0 :                         break;
   15119                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   15120                 :          0 :                         rss = actions->conf;
   15121                 :          0 :                         rss_desc->symmetric_hash_function =
   15122                 :          0 :                                 MLX5_RSS_IS_SYMM(rss->func);
   15123                 :          0 :                         memcpy(rss_desc->queue, rss->queue,
   15124         [ #  # ]:          0 :                                rss->queue_num * sizeof(uint16_t));
   15125                 :          0 :                         rss_desc->queue_num = rss->queue_num;
   15126                 :            :                         /* NULL RSS key indicates default RSS key. */
   15127         [ #  # ]:          0 :                         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   15128         [ #  # ]:          0 :                         memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   15129                 :            :                         /*
   15130                 :            :                          * rss->level and rss.types should be set in advance
   15131                 :            :                          * when expanding items for RSS.
   15132                 :            :                          */
   15133                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
   15134                 :          0 :                         dev_flow->handle->fate_action = rss_desc->shared_rss ?
   15135         [ #  # ]:          0 :                                 MLX5_FLOW_FATE_SHARED_RSS :
   15136                 :            :                                 MLX5_FLOW_FATE_QUEUE;
   15137                 :          0 :                         break;
   15138                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
   15139                 :          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15140                 :          0 :                         age_act = flow_aso_age_get_by_idx(dev, owner_idx);
   15141         [ #  # ]:          0 :                         if (flow->age == 0) {
   15142                 :          0 :                                 flow->age = owner_idx;
   15143                 :          0 :                                 rte_atomic_fetch_add_explicit(&age_act->refcnt, 1,
   15144                 :            :                                                    rte_memory_order_relaxed);
   15145                 :            :                         }
   15146                 :          0 :                         age_act_pos = actions_n++;
   15147                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
   15148                 :          0 :                         break;
   15149                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
   15150                 :          0 :                         dev_flow->dv.actions[actions_n] =
   15151                 :          0 :                                 flow_dv_translate_action_send_to_kernel(dev, attr,
   15152                 :            :                                                         error);
   15153         [ #  # ]:          0 :                         if (!dev_flow->dv.actions[actions_n])
   15154                 :          0 :                                 return -rte_errno;
   15155                 :          0 :                         actions_n++;
   15156                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
   15157                 :          0 :                         dev_flow->handle->fate_action =
   15158                 :            :                                         MLX5_FLOW_FATE_SEND_TO_KERNEL;
   15159                 :          0 :                         break;
   15160                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   15161                 :          0 :                         non_shared_age = action->conf;
   15162                 :          0 :                         age_act_pos = actions_n++;
   15163                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
   15164                 :          0 :                         break;
   15165                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
   15166         [ #  # ]:          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15167                 :            :                         cnt_act = flow_dv_counter_get_by_idx(dev, owner_idx,
   15168                 :            :                                                              NULL);
   15169                 :            :                         MLX5_ASSERT(cnt_act != NULL);
   15170                 :            :                         /**
   15171                 :            :                          * When creating meter drop flow in drop table, the
   15172                 :            :                          * counter should not overwrite the rte flow counter.
   15173                 :            :                          */
   15174         [ #  # ]:          0 :                         if (attr->group == MLX5_FLOW_TABLE_LEVEL_METER &&
   15175         [ #  # ]:          0 :                             dev_flow->dv.table_id == MLX5_MTR_TABLE_ID_DROP) {
   15176                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15177                 :          0 :                                                         cnt_act->action;
   15178                 :            :                         } else {
   15179         [ #  # ]:          0 :                                 if (flow->counter == 0) {
   15180                 :          0 :                                         flow->counter = owner_idx;
   15181                 :          0 :                                         rte_atomic_fetch_add_explicit
   15182                 :            :                                                 (&cnt_act->shared_info.refcnt,
   15183                 :            :                                                  1, rte_memory_order_relaxed);
   15184                 :            :                                 }
   15185                 :            :                                 /* Save information first, will apply later. */
   15186                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_COUNT;
   15187                 :            :                         }
   15188                 :            :                         break;
   15189                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   15190         [ #  # ]:          0 :                         if (!priv->sh->cdev->config.devx) {
   15191                 :          0 :                                 return rte_flow_error_set
   15192                 :            :                                               (error, ENOTSUP,
   15193                 :            :                                                RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15194                 :            :                                                NULL,
   15195                 :            :                                                "count action not supported");
   15196                 :            :                         }
   15197                 :            :                         /* Save information first, will apply later. */
   15198                 :          0 :                         count = action->conf;
   15199                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
   15200                 :          0 :                         break;
   15201                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
   15202                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15203                 :          0 :                                                 priv->sh->pop_vlan_action;
   15204                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
   15205                 :          0 :                         break;
   15206                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
   15207         [ #  # ]:          0 :                         if (!(action_flags &
   15208                 :            :                               MLX5_FLOW_ACTION_OF_SET_VLAN_VID))
   15209                 :          0 :                                 flow_dev_get_vlan_info_from_items(items, &vlan);
   15210         [ #  # ]:          0 :                         vlan.eth_proto = rte_be_to_cpu_16
   15211                 :            :                              ((((const struct rte_flow_action_of_push_vlan *)
   15212                 :            :                                                    actions->conf)->ethertype));
   15213                 :          0 :                         found_action = mlx5_flow_find_action
   15214                 :            :                                         (actions + 1,
   15215                 :            :                                          RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID);
   15216         [ #  # ]:          0 :                         if (found_action)
   15217                 :          0 :                                 mlx5_update_vlan_vid_pcp(found_action, &vlan);
   15218                 :          0 :                         found_action = mlx5_flow_find_action
   15219                 :            :                                         (actions + 1,
   15220                 :            :                                          RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP);
   15221         [ #  # ]:          0 :                         if (found_action)
   15222                 :          0 :                                 mlx5_update_vlan_vid_pcp(found_action, &vlan);
   15223         [ #  # ]:          0 :                         if (flow_dv_create_action_push_vlan
   15224                 :            :                                             (dev, attr, &vlan, dev_flow, error))
   15225                 :          0 :                                 return -rte_errno;
   15226                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15227                 :          0 :                                         dev_flow->dv.push_vlan_res->action;
   15228                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
   15229                 :          0 :                         break;
   15230                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
   15231                 :            :                         /* of_vlan_push action handled this action */
   15232                 :            :                         MLX5_ASSERT(action_flags &
   15233                 :            :                                     MLX5_FLOW_ACTION_OF_PUSH_VLAN);
   15234                 :            :                         break;
   15235                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
   15236         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
   15237                 :            :                                 break;
   15238                 :          0 :                         flow_dev_get_vlan_info_from_items(items, &vlan);
   15239                 :          0 :                         mlx5_update_vlan_vid_pcp(actions, &vlan);
   15240                 :            :                         /* If no VLAN push - this is a modify header action */
   15241         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_vlan_vid
   15242                 :            :                                                 (mhdr_res, actions, error))
   15243                 :          0 :                                 return -rte_errno;
   15244                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
   15245                 :          0 :                         break;
   15246                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   15247                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   15248         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_encap(dev, actions,
   15249                 :            :                                                            dev_flow,
   15250                 :          0 :                                                            attr->transfer,
   15251                 :            :                                                            error))
   15252                 :          0 :                                 return -rte_errno;
   15253                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15254                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15255                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   15256         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
   15257                 :          0 :                                 sample_act->action_flags |=
   15258                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15259                 :            :                         break;
   15260                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
   15261                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
   15262         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_decap(dev, dev_flow,
   15263                 :          0 :                                                            attr->transfer,
   15264                 :            :                                                            error))
   15265                 :          0 :                                 return -rte_errno;
   15266                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15267                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15268                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   15269                 :          0 :                         break;
   15270                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   15271                 :            :                         /* Handle encap with preceding decap. */
   15272         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_DECAP) {
   15273         [ #  # ]:          0 :                                 if (flow_dv_create_action_raw_encap
   15274                 :            :                                         (dev, actions, dev_flow, attr, error))
   15275                 :          0 :                                         return -rte_errno;
   15276                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15277                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15278                 :            :                         } else {
   15279                 :            :                                 /* Handle encap without preceding decap. */
   15280         [ #  # ]:          0 :                                 if (flow_dv_create_action_l2_encap
   15281                 :          0 :                                     (dev, actions, dev_flow, attr->transfer,
   15282                 :            :                                      error))
   15283                 :          0 :                                         return -rte_errno;
   15284                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15285                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15286                 :            :                         }
   15287                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   15288         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
   15289                 :          0 :                                 sample_act->action_flags |=
   15290                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15291                 :            :                         break;
   15292                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
   15293         [ #  # ]:          0 :                         while ((++action)->type == RTE_FLOW_ACTION_TYPE_VOID)
   15294                 :            :                                 ;
   15295         [ #  # ]:          0 :                         if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
   15296         [ #  # ]:          0 :                                 if (flow_dv_create_action_l2_decap
   15297                 :          0 :                                     (dev, dev_flow, attr->transfer, error))
   15298                 :          0 :                                         return -rte_errno;
   15299                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15300                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15301                 :            :                         }
   15302                 :            :                         /* If decap is followed by encap, handle it at encap. */
   15303                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   15304                 :          0 :                         break;
   15305                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_JUMP:
   15306                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15307                 :          0 :                                 (void *)(uintptr_t)action->conf;
   15308                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
   15309                 :          0 :                         break;
   15310                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
   15311                 :          0 :                         jump_group = ((const struct rte_flow_action_jump *)
   15312                 :          0 :                                                         action->conf)->group;
   15313                 :          0 :                         grp_info.std_tbl_fix = 0;
   15314         [ #  # ]:          0 :                         if (dev_flow->skip_scale &
   15315                 :            :                                 (1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT))
   15316                 :          0 :                                 grp_info.skip_scale = 1;
   15317                 :            :                         else
   15318                 :          0 :                                 grp_info.skip_scale = 0;
   15319                 :          0 :                         ret = mlx5_flow_group_to_table(dev, tunnel,
   15320                 :            :                                                        jump_group,
   15321                 :            :                                                        &table,
   15322                 :            :                                                        &grp_info, error);
   15323         [ #  # ]:          0 :                         if (ret)
   15324                 :          0 :                                 return ret;
   15325                 :          0 :                         tbl = flow_dv_tbl_resource_get(dev, table, attr->egress,
   15326                 :          0 :                                                        attr->transfer,
   15327                 :          0 :                                                        !!dev_flow->external,
   15328                 :            :                                                        tunnel, jump_group, 0,
   15329                 :            :                                                        0, error);
   15330         [ #  # ]:          0 :                         if (!tbl)
   15331                 :          0 :                                 return rte_flow_error_set
   15332                 :          0 :                                                 (error, errno,
   15333                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
   15334                 :            :                                                  NULL,
   15335                 :            :                                                  "cannot create jump action.");
   15336                 :            :                         if (flow_dv_jump_tbl_resource_register
   15337                 :            :                             (dev, tbl, dev_flow, error)) {
   15338                 :            :                                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   15339                 :            :                                 return rte_flow_error_set
   15340                 :            :                                                 (error, errno,
   15341                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
   15342                 :            :                                                  NULL,
   15343                 :            :                                                  "cannot create jump action.");
   15344                 :            :                         }
   15345                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15346                 :          0 :                                         dev_flow->dv.jump->action;
   15347                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
   15348                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP;
   15349                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_JUMP;
   15350                 :          0 :                         num_of_dest++;
   15351                 :          0 :                         break;
   15352                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
   15353                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
   15354         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_mac
   15355                 :            :                                         (mhdr_res, actions, error))
   15356                 :          0 :                                 return -rte_errno;
   15357                 :          0 :                         action_flags |= actions->type ==
   15358                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
   15359         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_MAC_SRC :
   15360                 :            :                                         MLX5_FLOW_ACTION_SET_MAC_DST;
   15361                 :          0 :                         break;
   15362                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
   15363                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
   15364         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv4
   15365                 :            :                                         (mhdr_res, actions, error))
   15366                 :          0 :                                 return -rte_errno;
   15367                 :          0 :                         action_flags |= actions->type ==
   15368                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
   15369         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_IPV4_SRC :
   15370                 :            :                                         MLX5_FLOW_ACTION_SET_IPV4_DST;
   15371                 :          0 :                         break;
   15372                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
   15373                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
   15374         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv6
   15375                 :            :                                         (mhdr_res, actions, error))
   15376                 :          0 :                                 return -rte_errno;
   15377                 :          0 :                         action_flags |= actions->type ==
   15378                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
   15379         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_IPV6_SRC :
   15380                 :            :                                         MLX5_FLOW_ACTION_SET_IPV6_DST;
   15381                 :          0 :                         break;
   15382                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
   15383                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
   15384         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tp
   15385                 :            :                                         (mhdr_res, actions, items,
   15386                 :          0 :                                          &flow_attr, dev_flow, !!(action_flags &
   15387                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15388                 :          0 :                                 return -rte_errno;
   15389                 :          0 :                         action_flags |= actions->type ==
   15390                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
   15391         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_TP_SRC :
   15392                 :            :                                         MLX5_FLOW_ACTION_SET_TP_DST;
   15393                 :          0 :                         break;
   15394                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
   15395         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_dec_ttl
   15396                 :            :                                         (mhdr_res, items, &flow_attr, dev_flow,
   15397                 :          0 :                                          !!(action_flags &
   15398                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15399                 :          0 :                                 return -rte_errno;
   15400                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEC_TTL;
   15401                 :          0 :                         break;
   15402                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
   15403         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ttl
   15404                 :            :                                         (mhdr_res, actions, items, &flow_attr,
   15405                 :          0 :                                          dev_flow, !!(action_flags &
   15406                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15407                 :          0 :                                 return -rte_errno;
   15408                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TTL;
   15409                 :          0 :                         break;
   15410                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
   15411                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
   15412         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tcp_seq
   15413                 :            :                                         (mhdr_res, actions, error))
   15414                 :          0 :                                 return -rte_errno;
   15415                 :          0 :                         action_flags |= actions->type ==
   15416                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
   15417         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_INC_TCP_SEQ :
   15418                 :            :                                         MLX5_FLOW_ACTION_DEC_TCP_SEQ;
   15419                 :          0 :                         break;
   15420                 :            : 
   15421                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
   15422                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
   15423         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tcp_ack
   15424                 :            :                                         (mhdr_res, actions, error))
   15425                 :          0 :                                 return -rte_errno;
   15426                 :          0 :                         action_flags |= actions->type ==
   15427                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
   15428         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_INC_TCP_ACK :
   15429                 :            :                                         MLX5_FLOW_ACTION_DEC_TCP_ACK;
   15430                 :          0 :                         break;
   15431                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
   15432         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_reg
   15433                 :            :                                         (mhdr_res, actions, error))
   15434                 :          0 :                                 return -rte_errno;
   15435                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15436                 :          0 :                         break;
   15437                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
   15438         [ #  # ]:          0 :                         if (flow_dv_convert_action_copy_mreg
   15439                 :            :                                         (dev, mhdr_res, actions, error))
   15440                 :          0 :                                 return -rte_errno;
   15441                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15442                 :          0 :                         break;
   15443                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
   15444                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
   15445                 :          0 :                         dev_flow->handle->fate_action =
   15446                 :            :                                         MLX5_FLOW_FATE_DEFAULT_MISS;
   15447                 :          0 :                         break;
   15448                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
   15449         [ #  # ]:          0 :                         if (!wks->fm)
   15450                 :          0 :                                 return rte_flow_error_set(error, rte_errno,
   15451                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
   15452                 :            :                                         NULL, "Failed to get meter in flow.");
   15453                 :            :                         /* Set the meter action. */
   15454                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15455                 :          0 :                                 wks->fm->meter_action_g;
   15456                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
   15457                 :          0 :                         break;
   15458                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
   15459         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv4_dscp(mhdr_res,
   15460                 :            :                                                               actions, error))
   15461                 :          0 :                                 return -rte_errno;
   15462                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
   15463                 :          0 :                         break;
   15464                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
   15465         [ #  # ]:          0 :                         if (mlx5_dv_modify_ipv6_traffic_class_supported(priv))
   15466                 :            :                                 ipv6_tc_off = MLX5_IPV6_HDR_DSCP_SHIFT;
   15467                 :            :                         else
   15468                 :            :                                 ipv6_tc_off = 0;
   15469         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv6_dscp(mhdr_res,
   15470                 :            :                                                               actions, ipv6_tc_off, error))
   15471                 :          0 :                                 return -rte_errno;
   15472                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
   15473                 :          0 :                         break;
   15474                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
   15475                 :          0 :                         sample_act_pos = actions_n;
   15476                 :          0 :                         sample = (const struct rte_flow_action_sample *)
   15477                 :            :                                  action->conf;
   15478                 :          0 :                         actions_n++;
   15479                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SAMPLE;
   15480                 :            :                         /* put encap action into group if work with port id */
   15481         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_ENCAP) &&
   15482                 :            :                             (action_flags & MLX5_FLOW_ACTION_PORT_ID))
   15483                 :          0 :                                 sample_act->action_flags |=
   15484                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15485                 :            :                         break;
   15486                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   15487         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_field
   15488                 :            :                                         (dev, mhdr_res, actions, attr, error))
   15489                 :          0 :                                 return -rte_errno;
   15490                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   15491                 :          0 :                         break;
   15492                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   15493                 :          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15494                 :          0 :                         ct = flow_aso_ct_get_by_idx(dev, owner_idx);
   15495         [ #  # ]:          0 :                         if (!ct)
   15496                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   15497                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15498                 :            :                                                 NULL,
   15499                 :            :                                                 "Failed to get CT object.");
   15500         [ #  # ]:          0 :                         if (mlx5_aso_ct_available(priv->sh, MLX5_HW_INV_QUEUE, ct))
   15501                 :          0 :                                 return rte_flow_error_set(error, rte_errno,
   15502                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15503                 :            :                                                 NULL,
   15504                 :            :                                                 "CT is unavailable.");
   15505         [ #  # ]:          0 :                         if (ct->is_original)
   15506                 :          0 :                                 dev_flow->dv.actions[actions_n] =
   15507                 :          0 :                                                         ct->dr_action_orig;
   15508                 :            :                         else
   15509                 :          0 :                                 dev_flow->dv.actions[actions_n] =
   15510                 :          0 :                                                         ct->dr_action_rply;
   15511         [ #  # ]:          0 :                         if (flow->ct == 0) {
   15512                 :          0 :                                 flow->indirect_type =
   15513                 :            :                                                 MLX5_INDIRECT_ACTION_TYPE_CT;
   15514                 :          0 :                                 flow->ct = owner_idx;
   15515                 :          0 :                                 rte_atomic_fetch_add_explicit(&ct->refcnt, 1,
   15516                 :            :                                                    rte_memory_order_relaxed);
   15517                 :            :                         }
   15518                 :          0 :                         actions_n++;
   15519                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
   15520                 :          0 :                         break;
   15521                 :          0 :                 case RTE_FLOW_ACTION_TYPE_END:
   15522                 :            :                         actions_end = true;
   15523         [ #  # ]:          0 :                         if (mhdr_res->actions_num) {
   15524                 :            :                                 /* create modify action if needed. */
   15525         [ #  # ]:          0 :                                 if (flow_dv_modify_hdr_resource_register
   15526                 :            :                                         (dev, mhdr_res, dev_flow, error))
   15527                 :          0 :                                         return -rte_errno;
   15528                 :          0 :                                 dev_flow->dv.actions[modify_action_position] =
   15529                 :          0 :                                         handle->dvh.modify_hdr->action;
   15530                 :            :                         }
   15531                 :            :                         /*
   15532                 :            :                          * Handle AGE and COUNT action by single HW counter
   15533                 :            :                          * when they are not shared.
   15534                 :            :                          */
   15535         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_AGE) {
   15536   [ #  #  #  # ]:          0 :                                 if ((non_shared_age && count) ||
   15537         [ #  # ]:          0 :                                     !flow_hit_aso_supported(priv, !dev_flow->dv.group)) {
   15538                 :            :                                         /* Creates age by counters. */
   15539                 :          0 :                                         cnt_act = flow_dv_prepare_counter
   15540                 :            :                                                                 (dev, dev_flow,
   15541                 :            :                                                                  flow, count,
   15542                 :            :                                                                  non_shared_age,
   15543                 :            :                                                                  error);
   15544         [ #  # ]:          0 :                                         if (!cnt_act)
   15545                 :          0 :                                                 return -rte_errno;
   15546                 :          0 :                                         dev_flow->dv.actions[age_act_pos] =
   15547                 :          0 :                                                                 cnt_act->action;
   15548                 :          0 :                                         break;
   15549                 :            :                                 }
   15550   [ #  #  #  # ]:          0 :                                 if (!flow->age && non_shared_age) {
   15551                 :          0 :                                         flow->age = flow_dv_aso_age_alloc
   15552                 :            :                                                                 (dev, error);
   15553         [ #  # ]:          0 :                                         if (!flow->age)
   15554                 :          0 :                                                 return -rte_errno;
   15555                 :          0 :                                         flow_dv_aso_age_params_init
   15556                 :            :                                                     (dev, flow->age,
   15557                 :          0 :                                                      non_shared_age->context ?
   15558                 :            :                                                      non_shared_age->context :
   15559                 :          0 :                                                      (void *)(uintptr_t)
   15560                 :          0 :                                                      (dev_flow->flow_idx),
   15561         [ #  # ]:          0 :                                                      non_shared_age->timeout);
   15562                 :            :                                 }
   15563                 :          0 :                                 age_act = flow_aso_age_get_by_idx(dev,
   15564                 :            :                                                                   flow->age);
   15565                 :          0 :                                 dev_flow->dv.actions[age_act_pos] =
   15566                 :          0 :                                                              age_act->dr_action;
   15567                 :            :                         }
   15568         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_COUNT) {
   15569                 :            :                                 /*
   15570                 :            :                                  * Create one count action, to be used
   15571                 :            :                                  * by all sub-flows.
   15572                 :            :                                  */
   15573                 :          0 :                                 cnt_act = flow_dv_prepare_counter(dev, dev_flow,
   15574                 :            :                                                                   flow, count,
   15575                 :            :                                                                   NULL, error);
   15576         [ #  # ]:          0 :                                 if (!cnt_act)
   15577                 :          0 :                                         return -rte_errno;
   15578                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15579                 :          0 :                                                                 cnt_act->action;
   15580                 :            :                         }
   15581                 :            :                 default:
   15582                 :            :                         break;
   15583                 :            :                 }
   15584   [ #  #  #  # ]:          0 :                 if (mhdr_res->actions_num &&
   15585                 :            :                     modify_action_position == UINT32_MAX)
   15586                 :          0 :                         modify_action_position = actions_n++;
   15587                 :            :         }
   15588                 :          0 :         dev_flow->act_flags = action_flags;
   15589                 :          0 :         ret = flow_dv_translate_items_sws(dev, dev_flow, attr, items, &matcher,
   15590                 :            :                                       error);
   15591         [ #  # ]:          0 :         if (ret)
   15592                 :          0 :                 return -rte_errno;
   15593         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_RSS) {
   15594                 :          0 :                 dev_flow->symmetric_hash_function = rss_desc->symmetric_hash_function;
   15595                 :          0 :                 flow_dv_hashfields_set(dev_flow->handle->layers,
   15596                 :            :                                        rss_desc,
   15597                 :            :                                        &dev_flow->hash_fields);
   15598                 :            :         }
   15599                 :            :         /* If has RSS action in the sample action, the Sample/Mirror resource
   15600                 :            :          * should be registered after the hash filed be update.
   15601                 :            :          */
   15602         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
   15603                 :          0 :                 ret = flow_dv_translate_action_sample(dev,
   15604                 :            :                                                       sample,
   15605                 :            :                                                       dev_flow, attr,
   15606                 :            :                                                       &num_of_dest,
   15607                 :            :                                                       sample_actions,
   15608                 :            :                                                       &sample_res,
   15609                 :            :                                                       error);
   15610         [ #  # ]:          0 :                 if (ret < 0)
   15611                 :            :                         return ret;
   15612                 :          0 :                 ret = flow_dv_create_action_sample(dev,
   15613                 :            :                                                    dev_flow,
   15614                 :            :                                                    num_of_dest,
   15615                 :            :                                                    &sample_res,
   15616                 :            :                                                    &mdest_res,
   15617                 :            :                                                    sample_actions,
   15618                 :            :                                                    action_flags,
   15619                 :            :                                                    error);
   15620         [ #  # ]:          0 :                 if (ret < 0)
   15621                 :          0 :                         return rte_flow_error_set
   15622                 :            :                                                 (error, rte_errno,
   15623                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15624                 :            :                                                 NULL,
   15625                 :            :                                                 "cannot create sample action");
   15626         [ #  # ]:          0 :                 if (num_of_dest > 1) {
   15627                 :          0 :                         dev_flow->dv.actions[sample_act_pos] =
   15628                 :          0 :                         dev_flow->dv.dest_array_res->action;
   15629                 :            :                 } else {
   15630                 :          0 :                         dev_flow->dv.actions[sample_act_pos] =
   15631                 :          0 :                         dev_flow->dv.sample_res->verbs_action;
   15632                 :            :                 }
   15633                 :            :         }
   15634                 :            :         /*
   15635                 :            :          * For multiple destination (sample action with ratio=1), the encap
   15636                 :            :          * action and port id action will be combined into group action.
   15637                 :            :          * So need remove the original these actions in the flow and only
   15638                 :            :          * use the sample action instead of.
   15639                 :            :          */
   15640         [ #  # ]:          0 :         if (num_of_dest > 1 &&
   15641   [ #  #  #  # ]:          0 :             (sample_act->dr_port_id_action || sample_act->dr_jump_action)) {
   15642                 :            :                 int i;
   15643                 :          0 :                 void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
   15644                 :            : 
   15645         [ #  # ]:          0 :                 for (i = 0; i < actions_n; i++) {
   15646         [ #  # ]:          0 :                         if ((sample_act->dr_encap_action &&
   15647                 :            :                                 sample_act->dr_encap_action ==
   15648   [ #  #  #  # ]:          0 :                                 dev_flow->dv.actions[i]) ||
   15649                 :          0 :                                 (sample_act->dr_port_id_action &&
   15650                 :            :                                 sample_act->dr_port_id_action ==
   15651         [ #  # ]:          0 :                                 dev_flow->dv.actions[i]) ||
   15652         [ #  # ]:          0 :                                 (sample_act->dr_jump_action &&
   15653                 :            :                                 sample_act->dr_jump_action ==
   15654         [ #  # ]:          0 :                                 dev_flow->dv.actions[i]))
   15655                 :          0 :                                 continue;
   15656                 :          0 :                         temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];
   15657                 :            :                 }
   15658                 :          0 :                 memcpy((void *)dev_flow->dv.actions,
   15659                 :            :                                 (void *)temp_actions,
   15660                 :            :                                 tmp_actions_n * sizeof(void *));
   15661                 :            :                 actions_n = tmp_actions_n;
   15662                 :            :         }
   15663                 :          0 :         dev_flow->dv.actions_n = actions_n;
   15664         [ #  # ]:          0 :         if (wks->skip_matcher_reg)
   15665                 :            :                 return 0;
   15666                 :            :         /* Register matcher. */
   15667                 :          0 :         matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
   15668                 :            :                                     matcher.mask.size);
   15669                 :          0 :         matcher.priority = mlx5_get_matcher_priority(dev, attr,
   15670                 :          0 :                                                      matcher.priority,
   15671                 :          0 :                                                      dev_flow->external);
   15672                 :            :         /**
   15673                 :            :          * When creating meter drop flow in drop table, using original
   15674                 :            :          * 5-tuple match, the matcher priority should be lower than
   15675                 :            :          * mtr_id matcher.
   15676                 :            :          */
   15677         [ #  # ]:          0 :         if (attr->group == MLX5_FLOW_TABLE_LEVEL_METER &&
   15678   [ #  #  #  # ]:          0 :             dev_flow->dv.table_id == MLX5_MTR_TABLE_ID_DROP &&
   15679                 :            :             matcher.priority <= MLX5_REG_BITS)
   15680                 :          0 :                 matcher.priority += MLX5_REG_BITS;
   15681                 :            :         /* reserved field no needs to be set to 0 here. */
   15682                 :          0 :         tbl_key.is_fdb = attr->transfer;
   15683                 :          0 :         tbl_key.is_egress = attr->egress;
   15684                 :          0 :         tbl_key.level = dev_flow->dv.group;
   15685                 :          0 :         tbl_key.id = dev_flow->dv.table_id;
   15686         [ #  # ]:          0 :         if (flow_dv_matcher_register(dev, &matcher, &tbl_key, dev_flow,
   15687                 :            :                                      tunnel, attr->group, error))
   15688                 :          0 :                 return -rte_errno;
   15689                 :            :         return 0;
   15690                 :            : }
   15691                 :            : 
   15692                 :            : /**
   15693                 :            :  * Set hash RX queue by hash fields (see enum ibv_rx_hash_fields)
   15694                 :            :  * and tunnel.
   15695                 :            :  *
   15696                 :            :  * @param[in, out] action
   15697                 :            :  *   Shred RSS action holding hash RX queue objects.
   15698                 :            :  * @param[in] hash_fields
   15699                 :            :  *   Defines combination of packet fields to participate in RX hash.
   15700                 :            :  * @param[in] tunnel
   15701                 :            :  *   Tunnel type
   15702                 :            :  * @param[in] hrxq_idx
   15703                 :            :  *   Hash RX queue index to set.
   15704                 :            :  *
   15705                 :            :  * @return
   15706                 :            :  *   0 on success, otherwise negative errno value.
   15707                 :            :  */
   15708                 :            : static int
   15709                 :          0 : __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
   15710                 :            :                               const uint64_t hash_fields,
   15711                 :            :                               uint32_t hrxq_idx)
   15712                 :            : {
   15713                 :            :         uint32_t *hrxqs = action->hrxq;
   15714                 :            : 
   15715   [ #  #  #  #  :          0 :         switch (hash_fields & ~IBV_RX_HASH_INNER) {
          #  #  #  #  #  
                   #  # ]
   15716                 :          0 :         case MLX5_RSS_HASH_IPV4:
   15717                 :            :                 /* fall-through. */
   15718                 :            :         case MLX5_RSS_HASH_IPV4_DST_ONLY:
   15719                 :            :                 /* fall-through. */
   15720                 :            :         case MLX5_RSS_HASH_IPV4_SRC_ONLY:
   15721                 :          0 :                 hrxqs[0] = hrxq_idx;
   15722                 :          0 :                 return 0;
   15723                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   15724                 :            :                 /* fall-through. */
   15725                 :            :         case MLX5_RSS_HASH_IPV4_TCP_DST_ONLY:
   15726                 :            :                 /* fall-through. */
   15727                 :            :         case MLX5_RSS_HASH_IPV4_TCP_SRC_ONLY:
   15728                 :          0 :                 hrxqs[1] = hrxq_idx;
   15729                 :          0 :                 return 0;
   15730                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   15731                 :            :                 /* fall-through. */
   15732                 :            :         case MLX5_RSS_HASH_IPV4_UDP_DST_ONLY:
   15733                 :            :                 /* fall-through. */
   15734                 :            :         case MLX5_RSS_HASH_IPV4_UDP_SRC_ONLY:
   15735                 :          0 :                 hrxqs[2] = hrxq_idx;
   15736                 :          0 :                 return 0;
   15737                 :          0 :         case MLX5_RSS_HASH_IPV6:
   15738                 :            :                 /* fall-through. */
   15739                 :            :         case MLX5_RSS_HASH_IPV6_DST_ONLY:
   15740                 :            :                 /* fall-through. */
   15741                 :            :         case MLX5_RSS_HASH_IPV6_SRC_ONLY:
   15742                 :          0 :                 hrxqs[3] = hrxq_idx;
   15743                 :          0 :                 return 0;
   15744                 :          0 :         case MLX5_RSS_HASH_IPV6_TCP:
   15745                 :            :                 /* fall-through. */
   15746                 :            :         case MLX5_RSS_HASH_IPV6_TCP_DST_ONLY:
   15747                 :            :                 /* fall-through. */
   15748                 :            :         case MLX5_RSS_HASH_IPV6_TCP_SRC_ONLY:
   15749                 :          0 :                 hrxqs[4] = hrxq_idx;
   15750                 :          0 :                 return 0;
   15751                 :          0 :         case MLX5_RSS_HASH_IPV6_UDP:
   15752                 :            :                 /* fall-through. */
   15753                 :            :         case MLX5_RSS_HASH_IPV6_UDP_DST_ONLY:
   15754                 :            :                 /* fall-through. */
   15755                 :            :         case MLX5_RSS_HASH_IPV6_UDP_SRC_ONLY:
   15756                 :          0 :                 hrxqs[5] = hrxq_idx;
   15757                 :          0 :                 return 0;
   15758                 :          0 :         case MLX5_RSS_HASH_NONE:
   15759                 :          0 :                 hrxqs[6] = hrxq_idx;
   15760                 :          0 :                 return 0;
   15761                 :          0 :         case MLX5_RSS_HASH_IPV4_ESP:
   15762                 :          0 :                 hrxqs[7] = hrxq_idx;
   15763                 :          0 :                 return 0;
   15764                 :          0 :         case MLX5_RSS_HASH_IPV6_ESP:
   15765                 :          0 :                 hrxqs[8] = hrxq_idx;
   15766                 :          0 :                 return 0;
   15767                 :          0 :         case MLX5_RSS_HASH_ESP_SPI:
   15768                 :          0 :                 hrxqs[9] = hrxq_idx;
   15769                 :          0 :                 return 0;
   15770                 :            :         default:
   15771                 :            :                 return -1;
   15772                 :            :         }
   15773                 :            : }
   15774                 :            : 
   15775                 :            : /**
   15776                 :            :  * Look up for hash RX queue by hash fields (see enum ibv_rx_hash_fields)
   15777                 :            :  * and tunnel.
   15778                 :            :  *
   15779                 :            :  * @param[in] dev
   15780                 :            :  *   Pointer to the Ethernet device structure.
   15781                 :            :  * @param[in] idx
   15782                 :            :  *   Shared RSS action ID holding hash RX queue objects.
   15783                 :            :  * @param[in] hash_fields
   15784                 :            :  *   Defines combination of packet fields to participate in RX hash.
   15785                 :            :  * @param[in] tunnel
   15786                 :            :  *   Tunnel type
   15787                 :            :  *
   15788                 :            :  * @return
   15789                 :            :  *   Valid hash RX queue index, otherwise 0.
   15790                 :            :  */
   15791                 :            : uint32_t
   15792                 :          0 : flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
   15793                 :            :                                const uint64_t hash_fields)
   15794                 :            : {
   15795                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15796                 :            :         struct mlx5_shared_action_rss *shared_rss =
   15797                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   15798                 :            :         const uint32_t *hrxqs = shared_rss->hrxq;
   15799                 :            : 
   15800   [ #  #  #  #  :          0 :         switch (hash_fields & ~IBV_RX_HASH_INNER) {
          #  #  #  #  #  
                   #  # ]
   15801                 :          0 :         case MLX5_RSS_HASH_IPV4:
   15802                 :            :                 /* fall-through. */
   15803                 :            :         case MLX5_RSS_HASH_IPV4_DST_ONLY:
   15804                 :            :                 /* fall-through. */
   15805                 :            :         case MLX5_RSS_HASH_IPV4_SRC_ONLY:
   15806                 :          0 :                 return hrxqs[0];
   15807                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   15808                 :            :                 /* fall-through. */
   15809                 :            :         case MLX5_RSS_HASH_IPV4_TCP_DST_ONLY:
   15810                 :            :                 /* fall-through. */
   15811                 :            :         case MLX5_RSS_HASH_IPV4_TCP_SRC_ONLY:
   15812                 :          0 :                 return hrxqs[1];
   15813                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   15814                 :            :                 /* fall-through. */
   15815                 :            :         case MLX5_RSS_HASH_IPV4_UDP_DST_ONLY:
   15816                 :            :                 /* fall-through. */
   15817                 :            :         case MLX5_RSS_HASH_IPV4_UDP_SRC_ONLY:
   15818                 :          0 :                 return hrxqs[2];
   15819                 :          0 :         case MLX5_RSS_HASH_IPV6:
   15820                 :            :                 /* fall-through. */
   15821                 :            :         case MLX5_RSS_HASH_IPV6_DST_ONLY:
   15822                 :            :                 /* fall-through. */
   15823                 :            :         case MLX5_RSS_HASH_IPV6_SRC_ONLY:
   15824                 :          0 :                 return hrxqs[3];
   15825                 :          0 :         case MLX5_RSS_HASH_IPV6_TCP:
   15826                 :            :                 /* fall-through. */
   15827                 :            :         case MLX5_RSS_HASH_IPV6_TCP_DST_ONLY:
   15828                 :            :                 /* fall-through. */
   15829                 :            :         case MLX5_RSS_HASH_IPV6_TCP_SRC_ONLY:
   15830                 :          0 :                 return hrxqs[4];
   15831                 :          0 :         case MLX5_RSS_HASH_IPV6_UDP:
   15832                 :            :                 /* fall-through. */
   15833                 :            :         case MLX5_RSS_HASH_IPV6_UDP_DST_ONLY:
   15834                 :            :                 /* fall-through. */
   15835                 :            :         case MLX5_RSS_HASH_IPV6_UDP_SRC_ONLY:
   15836                 :          0 :                 return hrxqs[5];
   15837                 :          0 :         case MLX5_RSS_HASH_NONE:
   15838                 :          0 :                 return hrxqs[6];
   15839                 :          0 :         case MLX5_RSS_HASH_IPV4_ESP:
   15840                 :          0 :                 return hrxqs[7];
   15841                 :          0 :         case MLX5_RSS_HASH_IPV6_ESP:
   15842                 :          0 :                 return hrxqs[8];
   15843                 :          0 :         case MLX5_RSS_HASH_ESP_SPI:
   15844                 :          0 :                 return hrxqs[9];
   15845                 :            :         default:
   15846                 :            :                 return 0;
   15847                 :            :         }
   15848                 :            : 
   15849                 :            : }
   15850                 :            : 
   15851                 :            : /**
   15852                 :            :  * Apply the flow to the NIC, lock free,
   15853                 :            :  * (mutex should be acquired by caller).
   15854                 :            :  *
   15855                 :            :  * @param[in] dev
   15856                 :            :  *   Pointer to the Ethernet device structure.
   15857                 :            :  * @param[in, out] flow
   15858                 :            :  *   Pointer to flow structure.
   15859                 :            :  * @param[out] error
   15860                 :            :  *   Pointer to error structure.
   15861                 :            :  *
   15862                 :            :  * @return
   15863                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   15864                 :            :  */
   15865                 :            : static int
   15866                 :          0 : flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
   15867                 :            :               struct rte_flow_error *error)
   15868                 :            : {
   15869                 :            :         struct mlx5_flow_dv_workspace *dv;
   15870                 :            :         struct mlx5_flow_handle *dh;
   15871                 :            :         struct mlx5_flow_handle_dv *dv_h;
   15872                 :            :         struct mlx5_flow *dev_flow;
   15873                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15874                 :            :         uint32_t handle_idx;
   15875                 :            :         int n;
   15876                 :            :         int err;
   15877                 :            :         int idx;
   15878                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   15879                 :          0 :         struct mlx5_flow_rss_desc *rss_desc = &wks->rss_desc;
   15880                 :            :         uint8_t misc_mask;
   15881                 :            : 
   15882                 :            :         MLX5_ASSERT(wks);
   15883         [ #  # ]:          0 :         for (idx = wks->flow_idx - 1; idx >= 0; idx--) {
   15884                 :          0 :                 dev_flow = &wks->flows[idx];
   15885                 :            :                 dv = &dev_flow->dv;
   15886                 :          0 :                 dh = dev_flow->handle;
   15887                 :            :                 dv_h = &dh->dvh;
   15888                 :          0 :                 n = dv->actions_n;
   15889         [ #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_DROP) {
   15890         [ #  # ]:          0 :                         if (dv->transfer) {
   15891                 :            :                                 MLX5_ASSERT(priv->sh->dr_drop_action);
   15892                 :          0 :                                 dv->actions[n++] = priv->sh->dr_drop_action;
   15893                 :            :                         } else {
   15894                 :            : #ifdef HAVE_MLX5DV_DR
   15895                 :            :                                 /* DR supports drop action placeholder. */
   15896                 :            :                                 MLX5_ASSERT(priv->sh->dr_drop_action);
   15897                 :          0 :                                 dv->actions[n++] = dv->group ?
   15898         [ #  # ]:          0 :                                         priv->sh->dr_drop_action :
   15899                 :            :                                         priv->root_drop_action;
   15900                 :            : #else
   15901                 :            :                                 /* For DV we use the explicit drop queue. */
   15902                 :            :                                 MLX5_ASSERT(priv->drop_queue.hrxq);
   15903                 :            :                                 dv->actions[n++] =
   15904                 :            :                                                 priv->drop_queue.hrxq->action;
   15905                 :            : #endif
   15906                 :            :                         }
   15907         [ #  # ]:          0 :                 } else if ((dh->fate_action == MLX5_FLOW_FATE_QUEUE &&
   15908   [ #  #  #  # ]:          0 :                            !dv_h->rix_sample && !dv_h->rix_dest_array)) {
   15909                 :            :                         struct mlx5_hrxq *hrxq;
   15910                 :            :                         uint32_t hrxq_idx;
   15911                 :            : 
   15912                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow, rss_desc,
   15913                 :            :                                                     &hrxq_idx);
   15914         [ #  # ]:          0 :                         if (!hrxq) {
   15915                 :          0 :                                 rte_flow_error_set
   15916                 :            :                                         (error, rte_errno,
   15917                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15918                 :            :                                          "cannot get hash queue");
   15919                 :          0 :                                 goto error;
   15920                 :            :                         }
   15921                 :          0 :                         dh->rix_hrxq = hrxq_idx;
   15922                 :          0 :                         dv->actions[n++] = hrxq->action;
   15923         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
   15924                 :            :                         struct mlx5_hrxq *hrxq = NULL;
   15925                 :            :                         uint32_t hrxq_idx;
   15926                 :            : 
   15927                 :          0 :                         hrxq_idx = flow_dv_action_rss_hrxq_lookup(dev,
   15928                 :            :                                                 rss_desc->shared_rss,
   15929                 :            :                                                 dev_flow->hash_fields);
   15930         [ #  # ]:          0 :                         if (hrxq_idx)
   15931                 :          0 :                                 hrxq = mlx5_ipool_get
   15932                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_HRXQ],
   15933                 :            :                                          hrxq_idx);
   15934         [ #  # ]:          0 :                         if (!hrxq) {
   15935                 :          0 :                                 rte_flow_error_set
   15936                 :            :                                         (error, rte_errno,
   15937                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15938                 :            :                                          "cannot get hash queue");
   15939                 :          0 :                                 goto error;
   15940                 :            :                         }
   15941                 :          0 :                         dh->rix_srss = rss_desc->shared_rss;
   15942                 :          0 :                         dv->actions[n++] = hrxq->action;
   15943         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_DEFAULT_MISS) {
   15944         [ #  # ]:          0 :                         if (!priv->sh->default_miss_action) {
   15945                 :          0 :                                 rte_flow_error_set
   15946                 :            :                                         (error, rte_errno,
   15947                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15948                 :            :                                          "default miss action not be created.");
   15949                 :          0 :                                 goto error;
   15950                 :            :                         }
   15951                 :          0 :                         dv->actions[n++] = priv->sh->default_miss_action;
   15952                 :            :                 }
   15953         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(dv_h->matcher->mask.buf);
   15954                 :            :                 __flow_dv_adjust_buf_size(&dv->value.size, misc_mask);
   15955                 :          0 :                 err = mlx5_flow_os_create_flow(dv_h->matcher->matcher_object,
   15956                 :          0 :                                                (void *)&dv->value, n,
   15957                 :          0 :                                                dv->actions, &dh->drv_flow);
   15958                 :            :                 if (err) {
   15959                 :          0 :                         rte_flow_error_set
   15960                 :          0 :                                 (error, errno,
   15961                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15962                 :            :                                 NULL,
   15963         [ #  # ]:          0 :                                 (!priv->sh->config.allow_duplicate_pattern &&
   15964         [ #  # ]:          0 :                                 errno == EEXIST) ?
   15965                 :            :                                 "duplicating pattern is not allowed" :
   15966                 :            :                                 "hardware refuses to create flow");
   15967                 :          0 :                         goto error;
   15968                 :            :                 }
   15969         [ #  # ]:          0 :                 if (priv->vmwa_context &&
   15970   [ #  #  #  # ]:          0 :                     dh->vf_vlan.tag && !dh->vf_vlan.created) {
   15971                 :            :                         /*
   15972                 :            :                          * The rule contains the VLAN pattern.
   15973                 :            :                          * For VF we are going to create VLAN
   15974                 :            :                          * interface to make hypervisor set correct
   15975                 :            :                          * e-Switch vport context.
   15976                 :            :                          */
   15977                 :          0 :                         mlx5_vlan_vmwa_acquire(dev, &dh->vf_vlan);
   15978                 :            :                 }
   15979                 :            :         }
   15980                 :            :         return 0;
   15981                 :          0 : error:
   15982                 :          0 :         err = rte_errno; /* Save rte_errno before cleanup. */
   15983   [ #  #  #  #  :          0 :         SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
                   #  # ]
   15984                 :            :                        handle_idx, dh, next) {
   15985                 :            :                 /* hrxq is union, don't clear it if the flag is not set. */
   15986   [ #  #  #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE && dh->rix_hrxq &&
   15987   [ #  #  #  # ]:          0 :                     !dh->dvh.rix_sample && !dh->dvh.rix_dest_array) {
   15988                 :          0 :                         mlx5_hrxq_release(dev, dh->rix_hrxq);
   15989                 :          0 :                         dh->rix_hrxq = 0;
   15990         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
   15991                 :          0 :                         dh->rix_srss = 0;
   15992                 :            :                 }
   15993   [ #  #  #  # ]:          0 :                 if (dh->vf_vlan.tag && dh->vf_vlan.created)
   15994                 :          0 :                         mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
   15995                 :            :         }
   15996                 :          0 :         rte_errno = err; /* Restore rte_errno. */
   15997                 :          0 :         return -rte_errno;
   15998                 :            : }
   15999                 :            : 
   16000                 :            : void
   16001                 :          0 : flow_matcher_remove_cb(void *tool_ctx __rte_unused,
   16002                 :            :                           struct mlx5_list_entry *entry)
   16003                 :            : {
   16004                 :            :         struct mlx5_flow_dv_matcher *resource = container_of(entry,
   16005                 :            :                                                              typeof(*resource),
   16006                 :            :                                                              entry);
   16007                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16008                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16009                 :            : 
   16010         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16011                 :          0 :                 claim_zero(mlx5dr_bwc_matcher_destroy((struct mlx5dr_bwc_matcher *)
   16012                 :            :                                                                 resource->matcher_object));
   16013                 :            :         else
   16014                 :            : #endif
   16015                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(resource->matcher_object));
   16016                 :          0 :         mlx5_free(resource);
   16017                 :          0 : }
   16018                 :            : 
   16019                 :            : /**
   16020                 :            :  * Release the flow matcher.
   16021                 :            :  *
   16022                 :            :  * @param dev
   16023                 :            :  *   Pointer to Ethernet device.
   16024                 :            :  * @param port_id
   16025                 :            :  *   Index to port ID action resource.
   16026                 :            :  *
   16027                 :            :  * @return
   16028                 :            :  *   1 while a reference on it exists, 0 when freed.
   16029                 :            :  */
   16030                 :            : static int
   16031                 :          0 : flow_dv_matcher_release(struct rte_eth_dev *dev,
   16032                 :            :                         struct mlx5_flow_handle *handle)
   16033                 :            : {
   16034                 :          0 :         struct mlx5_flow_dv_matcher *matcher = handle->dvh.matcher;
   16035                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(matcher->tbl,
   16036                 :            :                                                             typeof(*tbl), tbl);
   16037                 :            :         int ret;
   16038                 :            : 
   16039                 :            :         MLX5_ASSERT(matcher->matcher_object);
   16040                 :          0 :         ret = mlx5_list_unregister(tbl->matchers, &matcher->entry);
   16041                 :          0 :         flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl->tbl);
   16042                 :          0 :         return ret;
   16043                 :            : }
   16044                 :            : 
   16045                 :            : void
   16046                 :          0 : flow_encap_decap_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16047                 :            : {
   16048                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16049                 :            :         struct mlx5_flow_dv_encap_decap_resource *res =
   16050                 :            :                                        container_of(entry, typeof(*res), entry);
   16051                 :            : 
   16052                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16053         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16054                 :          0 :                 claim_zero(mlx5dr_action_destroy(res->action));
   16055                 :            :         else
   16056                 :            : #endif
   16057                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
   16058                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx);
   16059                 :          0 : }
   16060                 :            : 
   16061                 :            : /**
   16062                 :            :  * Release an encap/decap resource.
   16063                 :            :  *
   16064                 :            :  * @param dev
   16065                 :            :  *   Pointer to Ethernet device.
   16066                 :            :  * @param encap_decap_idx
   16067                 :            :  *   Index of encap decap resource.
   16068                 :            :  *
   16069                 :            :  * @return
   16070                 :            :  *   1 while a reference on it exists, 0 when freed.
   16071                 :            :  */
   16072                 :            : int
   16073                 :          0 : flow_encap_decap_resource_release(struct rte_eth_dev *dev,
   16074                 :            :                                      uint32_t encap_decap_idx)
   16075                 :            : {
   16076                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16077                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
   16078                 :            : 
   16079                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
   16080                 :            :                                   encap_decap_idx);
   16081         [ #  # ]:          0 :         if (!resource)
   16082                 :            :                 return 0;
   16083                 :            :         MLX5_ASSERT(resource->action);
   16084                 :          0 :         return mlx5_hlist_unregister(priv->sh->encaps_decaps, &resource->entry);
   16085                 :            : }
   16086                 :            : 
   16087                 :            : /**
   16088                 :            :  * Release an jump to table action resource.
   16089                 :            :  *
   16090                 :            :  * @param dev
   16091                 :            :  *   Pointer to Ethernet device.
   16092                 :            :  * @param rix_jump
   16093                 :            :  *   Index to the jump action resource.
   16094                 :            :  *
   16095                 :            :  * @return
   16096                 :            :  *   1 while a reference on it exists, 0 when freed.
   16097                 :            :  */
   16098                 :            : static int
   16099                 :          0 : flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
   16100                 :            :                                   uint32_t rix_jump)
   16101                 :            : {
   16102                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16103                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   16104                 :            : 
   16105                 :          0 :         tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP],
   16106                 :            :                                   rix_jump);
   16107         [ #  # ]:          0 :         if (!tbl_data)
   16108                 :            :                 return 0;
   16109                 :          0 :         return flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl_data->tbl);
   16110                 :            : }
   16111                 :            : 
   16112                 :            : void
   16113                 :          0 : flow_modify_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16114                 :            : {
   16115                 :            :         struct mlx5_flow_dv_modify_hdr_resource *res =
   16116                 :            :                 container_of(entry, typeof(*res), entry);
   16117                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16118                 :            : 
   16119                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16120         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16121                 :          0 :                 claim_zero(mlx5dr_action_destroy(res->action));
   16122                 :            :         else
   16123                 :            : #endif
   16124                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
   16125                 :          0 :         mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
   16126                 :          0 : }
   16127                 :            : 
   16128                 :            : /**
   16129                 :            :  * Release a modify-header resource.
   16130                 :            :  *
   16131                 :            :  * @param dev
   16132                 :            :  *   Pointer to Ethernet device.
   16133                 :            :  * @param handle
   16134                 :            :  *   Pointer to mlx5_flow_handle.
   16135                 :            :  *
   16136                 :            :  * @return
   16137                 :            :  *   1 while a reference on it exists, 0 when freed.
   16138                 :            :  */
   16139                 :            : static int
   16140                 :            : flow_dv_modify_hdr_resource_release(struct rte_eth_dev *dev,
   16141                 :            :                                     struct mlx5_flow_handle *handle)
   16142                 :            : {
   16143                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16144                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry = handle->dvh.modify_hdr;
   16145                 :            : 
   16146                 :            :         MLX5_ASSERT(entry->action);
   16147                 :          0 :         return mlx5_hlist_unregister(priv->sh->modify_cmds, &entry->entry);
   16148                 :            : }
   16149                 :            : 
   16150                 :            : void
   16151                 :          0 : flow_dv_port_id_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16152                 :            : {
   16153                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16154                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource =
   16155                 :            :                                   container_of(entry, typeof(*resource), entry);
   16156                 :            : 
   16157                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16158                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], resource->idx);
   16159                 :          0 : }
   16160                 :            : 
   16161                 :            : /**
   16162                 :            :  * Release port ID action resource.
   16163                 :            :  *
   16164                 :            :  * @param dev
   16165                 :            :  *   Pointer to Ethernet device.
   16166                 :            :  * @param handle
   16167                 :            :  *   Pointer to mlx5_flow_handle.
   16168                 :            :  *
   16169                 :            :  * @return
   16170                 :            :  *   1 while a reference on it exists, 0 when freed.
   16171                 :            :  */
   16172                 :            : static int
   16173                 :          0 : flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
   16174                 :            :                                         uint32_t port_id)
   16175                 :            : {
   16176                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16177                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
   16178                 :            : 
   16179                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID], port_id);
   16180         [ #  # ]:          0 :         if (!resource)
   16181                 :            :                 return 0;
   16182                 :            :         MLX5_ASSERT(resource->action);
   16183                 :          0 :         return mlx5_list_unregister(priv->sh->port_id_action_list,
   16184                 :            :                                     &resource->entry);
   16185                 :            : }
   16186                 :            : 
   16187                 :            : /**
   16188                 :            :  * Release shared RSS action resource.
   16189                 :            :  *
   16190                 :            :  * @param dev
   16191                 :            :  *   Pointer to Ethernet device.
   16192                 :            :  * @param srss
   16193                 :            :  *   Shared RSS action index.
   16194                 :            :  */
   16195                 :            : static void
   16196                 :          0 : flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss)
   16197                 :            : {
   16198                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16199                 :            :         struct mlx5_shared_action_rss *shared_rss;
   16200                 :            : 
   16201                 :          0 :         shared_rss = mlx5_ipool_get
   16202                 :          0 :                         (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], srss);
   16203                 :          0 :         rte_atomic_fetch_sub_explicit(&shared_rss->refcnt, 1, rte_memory_order_relaxed);
   16204                 :          0 : }
   16205                 :            : 
   16206                 :            : void
   16207                 :          0 : flow_dv_push_vlan_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16208                 :            : {
   16209                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16210                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource =
   16211                 :            :                         container_of(entry, typeof(*resource), entry);
   16212                 :            : 
   16213                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16214                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], resource->idx);
   16215                 :          0 : }
   16216                 :            : 
   16217                 :            : /**
   16218                 :            :  * Release push vlan action resource.
   16219                 :            :  *
   16220                 :            :  * @param dev
   16221                 :            :  *   Pointer to Ethernet device.
   16222                 :            :  * @param handle
   16223                 :            :  *   Pointer to mlx5_flow_handle.
   16224                 :            :  *
   16225                 :            :  * @return
   16226                 :            :  *   1 while a reference on it exists, 0 when freed.
   16227                 :            :  */
   16228                 :            : static int
   16229                 :          0 : flow_dv_push_vlan_action_resource_release(struct rte_eth_dev *dev,
   16230                 :            :                                           struct mlx5_flow_handle *handle)
   16231                 :            : {
   16232                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16233                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
   16234                 :          0 :         uint32_t idx = handle->dvh.rix_push_vlan;
   16235                 :            : 
   16236                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx);
   16237         [ #  # ]:          0 :         if (!resource)
   16238                 :            :                 return 0;
   16239                 :            :         MLX5_ASSERT(resource->action);
   16240                 :          0 :         return mlx5_list_unregister(priv->sh->push_vlan_action_list,
   16241                 :            :                                     &resource->entry);
   16242                 :            : }
   16243                 :            : 
   16244                 :            : /**
   16245                 :            :  * Release the fate resource.
   16246                 :            :  *
   16247                 :            :  * @param dev
   16248                 :            :  *   Pointer to Ethernet device.
   16249                 :            :  * @param handle
   16250                 :            :  *   Pointer to mlx5_flow_handle.
   16251                 :            :  */
   16252                 :            : static void
   16253                 :          0 : flow_dv_fate_resource_release(struct rte_eth_dev *dev,
   16254                 :            :                                struct mlx5_flow_handle *handle)
   16255                 :            : {
   16256         [ #  # ]:          0 :         if (!handle->rix_fate)
   16257                 :            :                 return;
   16258   [ #  #  #  #  :          0 :         switch (handle->fate_action) {
                      # ]
   16259                 :          0 :         case MLX5_FLOW_FATE_QUEUE:
   16260   [ #  #  #  # ]:          0 :                 if (!handle->dvh.rix_sample && !handle->dvh.rix_dest_array)
   16261                 :          0 :                         mlx5_hrxq_release(dev, handle->rix_hrxq);
   16262                 :            :                 break;
   16263                 :          0 :         case MLX5_FLOW_FATE_JUMP:
   16264                 :          0 :                 flow_dv_jump_tbl_resource_release(dev, handle->rix_jump);
   16265                 :          0 :                 break;
   16266                 :          0 :         case MLX5_FLOW_FATE_PORT_ID:
   16267                 :          0 :                 flow_dv_port_id_action_resource_release(dev,
   16268                 :            :                                 handle->rix_port_id_action);
   16269                 :          0 :                 break;
   16270                 :            :         case MLX5_FLOW_FATE_SEND_TO_KERNEL:
   16271                 :            :                 /* In case of send_to_kernel action the actual release of
   16272                 :            :                  * resource is done when all shared DR resources are released
   16273                 :            :                  * since this resource is created once and always reused.
   16274                 :            :                  */
   16275                 :            :                 break;
   16276                 :          0 :         default:
   16277                 :          0 :                 DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action);
   16278                 :          0 :                 break;
   16279                 :            :         }
   16280                 :          0 :         handle->rix_fate = 0;
   16281                 :            : }
   16282                 :            : 
   16283                 :            : void
   16284                 :          0 : flow_dv_sample_remove_cb(void *tool_ctx __rte_unused,
   16285                 :            :                          struct mlx5_list_entry *entry)
   16286                 :            : {
   16287                 :            :         struct mlx5_flow_dv_sample_resource *resource = container_of(entry,
   16288                 :            :                                                               typeof(*resource),
   16289                 :            :                                                               entry);
   16290                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   16291                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16292                 :            : 
   16293         [ #  # ]:          0 :         if (resource->verbs_action)
   16294                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action
   16295                 :            :                                                       (resource->verbs_action));
   16296         [ #  # ]:          0 :         if (resource->normal_path_tbl)
   16297                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   16298                 :            :                                              resource->normal_path_tbl);
   16299                 :          0 :         flow_dv_sample_sub_actions_release(dev, &resource->sample_idx);
   16300                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], resource->idx);
   16301                 :          0 :         DRV_LOG(DEBUG, "sample resource %p: removed", (void *)resource);
   16302                 :          0 : }
   16303                 :            : 
   16304                 :            : /**
   16305                 :            :  * Release an sample resource.
   16306                 :            :  *
   16307                 :            :  * @param dev
   16308                 :            :  *   Pointer to Ethernet device.
   16309                 :            :  * @param handle
   16310                 :            :  *   Pointer to mlx5_flow_handle.
   16311                 :            :  *
   16312                 :            :  * @return
   16313                 :            :  *   1 while a reference on it exists, 0 when freed.
   16314                 :            :  */
   16315                 :            : static int
   16316                 :          0 : flow_dv_sample_resource_release(struct rte_eth_dev *dev,
   16317                 :            :                                      struct mlx5_flow_handle *handle)
   16318                 :            : {
   16319                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16320                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   16321                 :            : 
   16322                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_SAMPLE],
   16323                 :            :                                   handle->dvh.rix_sample);
   16324         [ #  # ]:          0 :         if (!resource)
   16325                 :            :                 return 0;
   16326                 :            :         MLX5_ASSERT(resource->verbs_action);
   16327                 :          0 :         return mlx5_list_unregister(priv->sh->sample_action_list,
   16328                 :            :                                     &resource->entry);
   16329                 :            : }
   16330                 :            : 
   16331                 :            : void
   16332                 :          0 : flow_dv_dest_array_remove_cb(void *tool_ctx __rte_unused,
   16333                 :            :                              struct mlx5_list_entry *entry)
   16334                 :            : {
   16335                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   16336                 :            :                         container_of(entry, typeof(*resource), entry);
   16337                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   16338                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16339                 :            :         uint32_t i = 0;
   16340                 :            : 
   16341                 :            :         MLX5_ASSERT(resource->action);
   16342         [ #  # ]:          0 :         if (resource->action)
   16343                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16344         [ #  # ]:          0 :         for (; i < resource->num_of_dest; i++)
   16345                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   16346                 :            :                                                    &resource->sample_idx[i]);
   16347                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], resource->idx);
   16348                 :          0 :         DRV_LOG(DEBUG, "destination array resource %p: removed",
   16349                 :            :                 (void *)resource);
   16350                 :          0 : }
   16351                 :            : 
   16352                 :            : /**
   16353                 :            :  * Release an destination array resource.
   16354                 :            :  *
   16355                 :            :  * @param dev
   16356                 :            :  *   Pointer to Ethernet device.
   16357                 :            :  * @param handle
   16358                 :            :  *   Pointer to mlx5_flow_handle.
   16359                 :            :  *
   16360                 :            :  * @return
   16361                 :            :  *   1 while a reference on it exists, 0 when freed.
   16362                 :            :  */
   16363                 :            : static int
   16364                 :          0 : flow_dv_dest_array_resource_release(struct rte_eth_dev *dev,
   16365                 :            :                                     struct mlx5_flow_handle *handle)
   16366                 :            : {
   16367                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16368                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   16369                 :            : 
   16370                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   16371                 :            :                                   handle->dvh.rix_dest_array);
   16372         [ #  # ]:          0 :         if (!resource)
   16373                 :            :                 return 0;
   16374                 :            :         MLX5_ASSERT(resource->action);
   16375                 :          0 :         return mlx5_list_unregister(priv->sh->dest_array_list,
   16376                 :            :                                     &resource->entry);
   16377                 :            : }
   16378                 :            : 
   16379                 :            : static void
   16380                 :          0 : flow_dev_geneve_tlv_option_resource_release(struct mlx5_dev_ctx_shared *sh)
   16381                 :            : {
   16382                 :          0 :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource =
   16383                 :            :                                 sh->geneve_tlv_option_resource;
   16384                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
   16385         [ #  # ]:          0 :         if (geneve_opt_resource) {
   16386         [ #  # ]:          0 :                 if (!(rte_atomic_fetch_sub_explicit(&geneve_opt_resource->refcnt, 1,
   16387                 :            :                                          rte_memory_order_relaxed) - 1)) {
   16388                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy
   16389                 :            :                                         (geneve_opt_resource->obj));
   16390                 :          0 :                         mlx5_free(sh->geneve_tlv_option_resource);
   16391                 :          0 :                         sh->geneve_tlv_option_resource = NULL;
   16392                 :            :                 }
   16393                 :            :         }
   16394                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
   16395                 :          0 : }
   16396                 :            : 
   16397                 :            : /**
   16398                 :            :  * Remove the flow from the NIC but keeps it in memory.
   16399                 :            :  * Lock free, (mutex should be acquired by caller).
   16400                 :            :  *
   16401                 :            :  * @param[in] dev
   16402                 :            :  *   Pointer to Ethernet device.
   16403                 :            :  * @param[in, out] flow
   16404                 :            :  *   Pointer to flow structure.
   16405                 :            :  */
   16406                 :            : static void
   16407                 :          0 : flow_dv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
   16408                 :            : {
   16409                 :            :         struct mlx5_flow_handle *dh;
   16410                 :            :         uint32_t handle_idx;
   16411                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16412                 :            : 
   16413         [ #  # ]:          0 :         if (!flow)
   16414                 :            :                 return;
   16415                 :          0 :         handle_idx = flow->dev_handles;
   16416         [ #  # ]:          0 :         while (handle_idx) {
   16417                 :          0 :                 dh = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   16418                 :            :                                     handle_idx);
   16419         [ #  # ]:          0 :                 if (!dh)
   16420                 :            :                         return;
   16421         [ #  # ]:          0 :                 if (dh->drv_flow) {
   16422                 :            :                         claim_zero(mlx5_flow_os_destroy_flow(dh->drv_flow));
   16423                 :          0 :                         dh->drv_flow = NULL;
   16424                 :            :                 }
   16425         [ #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE)
   16426                 :          0 :                         flow_dv_fate_resource_release(dev, dh);
   16427   [ #  #  #  # ]:          0 :                 if (dh->vf_vlan.tag && dh->vf_vlan.created)
   16428                 :          0 :                         mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
   16429                 :          0 :                 handle_idx = dh->next.next;
   16430                 :            :         }
   16431                 :            : }
   16432                 :            : 
   16433                 :            : /**
   16434                 :            :  * Remove the flow from the NIC and the memory.
   16435                 :            :  * Lock free, (mutex should be acquired by caller).
   16436                 :            :  *
   16437                 :            :  * @param[in] dev
   16438                 :            :  *   Pointer to the Ethernet device structure.
   16439                 :            :  * @param[in, out] flow
   16440                 :            :  *   Pointer to flow structure.
   16441                 :            :  */
   16442                 :            : static void
   16443                 :          0 : flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
   16444                 :            : {
   16445                 :            :         struct mlx5_flow_handle *dev_handle;
   16446                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16447                 :            :         struct mlx5_flow_meter_info *fm = NULL;
   16448                 :            :         uint32_t srss = 0;
   16449                 :            : 
   16450         [ #  # ]:          0 :         if (!flow)
   16451                 :            :                 return;
   16452                 :          0 :         flow_dv_remove(dev, flow);
   16453         [ #  # ]:          0 :         if (flow->counter) {
   16454                 :          0 :                 flow_dv_counter_free(dev, flow->counter);
   16455                 :          0 :                 flow->counter = 0;
   16456                 :            :         }
   16457         [ #  # ]:          0 :         if (flow->meter) {
   16458                 :          0 :                 fm = flow_dv_meter_find_by_idx(priv, flow->meter);
   16459         [ #  # ]:          0 :                 if (fm)
   16460                 :          0 :                         mlx5_flow_meter_detach(priv, fm);
   16461                 :          0 :                 flow->meter = 0;
   16462                 :            :         }
   16463                 :            :         /* Keep the current age handling by default. */
   16464   [ #  #  #  # ]:          0 :         if (flow->indirect_type == MLX5_INDIRECT_ACTION_TYPE_CT && flow->ct)
   16465                 :          0 :                 flow_dv_aso_ct_release(dev, flow->ct, NULL);
   16466         [ #  # ]:          0 :         else if (flow->age)
   16467                 :          0 :                 flow_dv_aso_age_release(dev, flow->age);
   16468         [ #  # ]:          0 :         while (flow->geneve_tlv_option) {
   16469                 :          0 :                 flow_dev_geneve_tlv_option_resource_release(priv->sh);
   16470                 :          0 :                 flow->geneve_tlv_option--;
   16471                 :            :         }
   16472         [ #  # ]:          0 :         while (flow->dev_handles) {
   16473                 :            :                 uint32_t tmp_idx = flow->dev_handles;
   16474                 :            : 
   16475                 :          0 :                 dev_handle = mlx5_ipool_get(priv->sh->ipool
   16476                 :            :                                             [MLX5_IPOOL_MLX5_FLOW], tmp_idx);
   16477         [ #  # ]:          0 :                 if (!dev_handle)
   16478                 :            :                         return;
   16479                 :          0 :                 flow->dev_handles = dev_handle->next.next;
   16480         [ #  # ]:          0 :                 while (dev_handle->flex_item) {
   16481                 :          0 :                         int index = rte_bsf32(dev_handle->flex_item);
   16482                 :            : 
   16483                 :          0 :                         mlx5_flex_release_index(dev, index);
   16484                 :          0 :                         dev_handle->flex_item &= ~(uint8_t)RTE_BIT32(index);
   16485                 :            :                 }
   16486         [ #  # ]:          0 :                 if (dev_handle->dvh.matcher)
   16487                 :          0 :                         flow_dv_matcher_release(dev, dev_handle);
   16488         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_sample)
   16489                 :          0 :                         flow_dv_sample_resource_release(dev, dev_handle);
   16490         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_dest_array)
   16491                 :          0 :                         flow_dv_dest_array_resource_release(dev, dev_handle);
   16492         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_encap_decap)
   16493                 :          0 :                         flow_encap_decap_resource_release(dev,
   16494                 :            :                                 dev_handle->dvh.rix_encap_decap);
   16495         [ #  # ]:          0 :                 if (dev_handle->dvh.modify_hdr)
   16496                 :            :                         flow_dv_modify_hdr_resource_release(dev, dev_handle);
   16497         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_push_vlan)
   16498                 :          0 :                         flow_dv_push_vlan_action_resource_release(dev,
   16499                 :            :                                                                   dev_handle);
   16500         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_tag)
   16501                 :          0 :                         flow_dv_tag_release(dev,
   16502                 :            :                                             dev_handle->dvh.rix_tag);
   16503         [ #  # ]:          0 :                 if (dev_handle->fate_action != MLX5_FLOW_FATE_SHARED_RSS)
   16504                 :          0 :                         flow_dv_fate_resource_release(dev, dev_handle);
   16505         [ #  # ]:          0 :                 else if (!srss)
   16506                 :          0 :                         srss = dev_handle->rix_srss;
   16507   [ #  #  #  # ]:          0 :                 if (fm && dev_handle->is_meter_flow_id &&
   16508         [ #  # ]:          0 :                     dev_handle->split_flow_id)
   16509                 :          0 :                         mlx5_ipool_free(fm->flow_ipool,
   16510                 :            :                                         dev_handle->split_flow_id);
   16511         [ #  # ]:          0 :                 else if (dev_handle->split_flow_id &&
   16512         [ #  # ]:          0 :                     !dev_handle->is_meter_flow_id)
   16513                 :          0 :                         mlx5_ipool_free(priv->sh->ipool
   16514                 :            :                                         [MLX5_IPOOL_RSS_EXPANTION_FLOW_ID],
   16515                 :            :                                         dev_handle->split_flow_id);
   16516                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   16517                 :            :                            tmp_idx);
   16518                 :            :         }
   16519         [ #  # ]:          0 :         if (srss)
   16520                 :          0 :                 flow_dv_shared_rss_action_release(dev, srss);
   16521                 :            : }
   16522                 :            : 
   16523                 :            : /**
   16524                 :            :  * Release array of hash RX queue objects.
   16525                 :            :  * Helper function.
   16526                 :            :  *
   16527                 :            :  * @param[in] dev
   16528                 :            :  *   Pointer to the Ethernet device structure.
   16529                 :            :  * @param[in, out] hrxqs
   16530                 :            :  *   Array of hash RX queue objects.
   16531                 :            :  *
   16532                 :            :  * @return
   16533                 :            :  *   Total number of references to hash RX queue objects in *hrxqs* array
   16534                 :            :  *   after this operation.
   16535                 :            :  */
   16536                 :            : static int
   16537                 :          0 : __flow_dv_hrxqs_release(struct rte_eth_dev *dev,
   16538                 :            :                         uint32_t (*hrxqs)[MLX5_RSS_HASH_FIELDS_LEN])
   16539                 :            : {
   16540                 :            :         size_t i;
   16541                 :            :         int remaining = 0;
   16542                 :            : 
   16543         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(*hrxqs); i++) {
   16544                 :          0 :                 int ret = mlx5_hrxq_release(dev, (*hrxqs)[i]);
   16545                 :            : 
   16546         [ #  # ]:          0 :                 if (!ret)
   16547                 :          0 :                         (*hrxqs)[i] = 0;
   16548                 :          0 :                 remaining += ret;
   16549                 :            :         }
   16550                 :          0 :         return remaining;
   16551                 :            : }
   16552                 :            : 
   16553                 :            : /**
   16554                 :            :  * Release all hash RX queue objects representing shared RSS action.
   16555                 :            :  *
   16556                 :            :  * @param[in] dev
   16557                 :            :  *   Pointer to the Ethernet device structure.
   16558                 :            :  * @param[in, out] action
   16559                 :            :  *   Shared RSS action to remove hash RX queue objects from.
   16560                 :            :  *
   16561                 :            :  * @return
   16562                 :            :  *   Total number of references to hash RX queue objects stored in *action*
   16563                 :            :  *   after this operation.
   16564                 :            :  *   Expected to be 0 if no external references held.
   16565                 :            :  */
   16566                 :            : static int
   16567                 :            : __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev,
   16568                 :            :                                  struct mlx5_shared_action_rss *shared_rss)
   16569                 :            : {
   16570                 :          0 :         return __flow_dv_hrxqs_release(dev, &shared_rss->hrxq);
   16571                 :            : }
   16572                 :            : 
   16573                 :            : /**
   16574                 :            :  * Adjust L3/L4 hash value of pre-created shared RSS hrxq according to
   16575                 :            :  * user input.
   16576                 :            :  *
   16577                 :            :  * Only one hash value is available for one L3+L4 combination:
   16578                 :            :  * for example:
   16579                 :            :  * MLX5_RSS_HASH_IPV4, MLX5_RSS_HASH_IPV4_SRC_ONLY, and
   16580                 :            :  * MLX5_RSS_HASH_IPV4_DST_ONLY are mutually exclusive so they can share
   16581                 :            :  * same slot in mlx5_rss_hash_fields.
   16582                 :            :  *
   16583                 :            :  * @param[in] orig_rss_types
   16584                 :            :  *   RSS type as provided in shared RSS action.
   16585                 :            :  * @param[in, out] hash_field
   16586                 :            :  *   hash_field variable needed to be adjusted.
   16587                 :            :  *
   16588                 :            :  * @return
   16589                 :            :  *   void
   16590                 :            :  */
   16591                 :            : void
   16592         [ #  # ]:          0 : flow_dv_action_rss_l34_hash_adjust(uint64_t orig_rss_types,
   16593                 :            :                                    uint64_t *hash_field)
   16594                 :            : {
   16595                 :            :         uint64_t rss_types = rte_eth_rss_hf_refine(orig_rss_types);
   16596                 :            : 
   16597   [ #  #  #  #  :          0 :         switch (*hash_field & ~IBV_RX_HASH_INNER) {
                      # ]
   16598                 :          0 :         case MLX5_RSS_HASH_IPV4:
   16599         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV4_LAYER_TYPES) {
   16600                 :          0 :                         *hash_field &= ~MLX5_RSS_HASH_IPV4;
   16601         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   16602                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_IPV4;
   16603         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   16604                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_IPV4;
   16605                 :            :                         else
   16606                 :          0 :                                 *hash_field |= MLX5_RSS_HASH_IPV4;
   16607                 :            :                 }
   16608                 :            :                 return;
   16609                 :          0 :         case MLX5_RSS_HASH_IPV6:
   16610         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV6_LAYER_TYPES) {
   16611                 :          0 :                         *hash_field &= ~MLX5_RSS_HASH_IPV6;
   16612         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   16613                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_IPV6;
   16614         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   16615                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_IPV6;
   16616                 :            :                         else
   16617                 :          0 :                                 *hash_field |= MLX5_RSS_HASH_IPV6;
   16618                 :            :                 }
   16619                 :            :                 return;
   16620                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   16621                 :            :                 /* fall-through. */
   16622                 :            :         case MLX5_RSS_HASH_IPV6_UDP:
   16623         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_UDP) {
   16624                 :          0 :                         *hash_field &= ~MLX5_UDP_IBV_RX_HASH;
   16625         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   16626                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_PORT_UDP;
   16627         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   16628                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_PORT_UDP;
   16629                 :            :                         else
   16630                 :          0 :                                 *hash_field |= MLX5_UDP_IBV_RX_HASH;
   16631                 :            :                 }
   16632                 :            :                 return;
   16633                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   16634                 :            :                 /* fall-through. */
   16635                 :            :         case MLX5_RSS_HASH_IPV6_TCP:
   16636         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_TCP) {
   16637                 :          0 :                         *hash_field &= ~MLX5_TCP_IBV_RX_HASH;
   16638         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   16639                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_PORT_TCP;
   16640         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   16641                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_PORT_TCP;
   16642                 :            :                         else
   16643                 :          0 :                                 *hash_field |= MLX5_TCP_IBV_RX_HASH;
   16644                 :            :                 }
   16645                 :            :                 return;
   16646                 :            :         default:
   16647                 :            :                 return;
   16648                 :            :         }
   16649                 :            : }
   16650                 :            : 
   16651                 :            : /**
   16652                 :            :  * Setup shared RSS action.
   16653                 :            :  * Prepare set of hash RX queue objects sufficient to handle all valid
   16654                 :            :  * hash_fields combinations (see enum ibv_rx_hash_fields).
   16655                 :            :  *
   16656                 :            :  * @param[in] dev
   16657                 :            :  *   Pointer to the Ethernet device structure.
   16658                 :            :  * @param[in] action_idx
   16659                 :            :  *   Shared RSS action ipool index.
   16660                 :            :  * @param[in, out] action
   16661                 :            :  *   Partially initialized shared RSS action.
   16662                 :            :  * @param[out] error
   16663                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16664                 :            :  *   error only.
   16665                 :            :  *
   16666                 :            :  * @return
   16667                 :            :  *   0 on success, otherwise negative errno value.
   16668                 :            :  */
   16669                 :            : static int
   16670                 :          0 : __flow_dv_action_rss_setup(struct rte_eth_dev *dev,
   16671                 :            :                            uint32_t action_idx,
   16672                 :            :                            struct mlx5_shared_action_rss *shared_rss,
   16673                 :            :                            struct rte_flow_error *error)
   16674                 :            : {
   16675                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16676                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { 0 };
   16677                 :            :         size_t i;
   16678                 :            :         int err;
   16679                 :            : 
   16680                 :          0 :         shared_rss->ind_tbl = mlx5_ind_table_obj_new
   16681                 :            :                               (dev, shared_rss->origin.queue,
   16682                 :            :                                shared_rss->origin.queue_num,
   16683                 :            :                                true,
   16684                 :          0 :                                !!dev->data->dev_started);
   16685         [ #  # ]:          0 :         if (!shared_rss->ind_tbl)
   16686                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   16687                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16688                 :            :                                           "cannot setup indirection table");
   16689                 :          0 :         memcpy(rss_desc.key, shared_rss->origin.key, MLX5_RSS_HASH_KEY_LEN);
   16690                 :          0 :         rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN;
   16691                 :          0 :         rss_desc.symmetric_hash_function =
   16692                 :          0 :                 MLX5_RSS_IS_SYMM(shared_rss->origin.func);
   16693                 :          0 :         rss_desc.const_q = shared_rss->origin.queue;
   16694                 :          0 :         rss_desc.queue_num = shared_rss->origin.queue_num;
   16695                 :            :         /* Set non-zero value to indicate a shared RSS. */
   16696                 :          0 :         rss_desc.shared_rss = action_idx;
   16697                 :          0 :         rss_desc.ind_tbl = shared_rss->ind_tbl;
   16698         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
   16699                 :          0 :                 rss_desc.hws_flags = MLX5DR_ACTION_FLAG_HWS_RX;
   16700         [ #  # ]:          0 :         for (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) {
   16701                 :            :                 struct mlx5_hrxq *hrxq;
   16702                 :          0 :                 uint64_t hash_fields = mlx5_rss_hash_fields[i];
   16703                 :            :                 int tunnel = 0;
   16704                 :            : 
   16705                 :          0 :                 flow_dv_action_rss_l34_hash_adjust(shared_rss->origin.types,
   16706                 :            :                                                    &hash_fields);
   16707         [ #  # ]:          0 :                 if (shared_rss->origin.level > 1) {
   16708                 :          0 :                         hash_fields |= IBV_RX_HASH_INNER;
   16709                 :            :                         tunnel = 1;
   16710                 :            :                 }
   16711                 :          0 :                 rss_desc.tunnel = tunnel;
   16712                 :          0 :                 rss_desc.hash_fields = hash_fields;
   16713                 :          0 :                 hrxq = mlx5_hrxq_get(dev, &rss_desc);
   16714         [ #  # ]:          0 :                 if (!hrxq) {
   16715                 :          0 :                         rte_flow_error_set
   16716                 :            :                                 (error, rte_errno,
   16717                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16718                 :            :                                  "cannot get hash queue");
   16719                 :          0 :                         goto error_hrxq_new;
   16720                 :            :                 }
   16721                 :          0 :                 err = __flow_dv_action_rss_hrxq_set
   16722                 :            :                         (shared_rss, hash_fields, hrxq->idx);
   16723                 :            :                 MLX5_ASSERT(!err);
   16724                 :            :         }
   16725                 :            :         return 0;
   16726                 :            : error_hrxq_new:
   16727                 :          0 :         err = rte_errno;
   16728                 :            :         __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
   16729         [ #  # ]:          0 :         if (!mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true))
   16730                 :          0 :                 shared_rss->ind_tbl = NULL;
   16731                 :          0 :         rte_errno = err;
   16732                 :          0 :         return -rte_errno;
   16733                 :            : }
   16734                 :            : 
   16735                 :            : /**
   16736                 :            :  * Create shared RSS action.
   16737                 :            :  *
   16738                 :            :  * @param[in] dev
   16739                 :            :  *   Pointer to the Ethernet device structure.
   16740                 :            :  * @param[in] conf
   16741                 :            :  *   Shared action configuration.
   16742                 :            :  * @param[in] rss
   16743                 :            :  *   RSS action specification used to create shared action.
   16744                 :            :  * @param[out] error
   16745                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16746                 :            :  *   error only.
   16747                 :            :  *
   16748                 :            :  * @return
   16749                 :            :  *   A valid shared action ID in case of success, 0 otherwise and
   16750                 :            :  *   rte_errno is set.
   16751                 :            :  */
   16752                 :            : static uint32_t
   16753                 :          0 : __flow_dv_action_rss_create(struct rte_eth_dev *dev,
   16754                 :            :                             const struct rte_flow_indir_action_conf *conf,
   16755                 :            :                             const struct rte_flow_action_rss *rss,
   16756                 :            :                             struct rte_flow_error *error)
   16757                 :            : {
   16758                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16759                 :            :         struct mlx5_shared_action_rss *shared_rss = NULL;
   16760                 :            :         struct rte_flow_action_rss *origin;
   16761                 :            :         const uint8_t *rss_key;
   16762                 :            :         uint32_t idx;
   16763                 :            : 
   16764                 :            :         RTE_SET_USED(conf);
   16765                 :          0 :         shared_rss = mlx5_ipool_zmalloc
   16766                 :          0 :                          (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], &idx);
   16767         [ #  # ]:          0 :         if (!shared_rss) {
   16768                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   16769                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16770                 :            :                                    "cannot allocate resource memory");
   16771                 :          0 :                 goto error_rss_init;
   16772                 :            :         }
   16773         [ #  # ]:          0 :         if (idx > (1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET)) {
   16774                 :          0 :                 rte_flow_error_set(error, E2BIG,
   16775                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16776                 :            :                                    "rss action number out of range");
   16777                 :          0 :                 goto error_rss_init;
   16778                 :            :         }
   16779                 :            :         origin = &shared_rss->origin;
   16780                 :          0 :         origin->func = rss->func;
   16781                 :          0 :         origin->level = rss->level;
   16782                 :            :         /* RSS type 0 indicates default RSS type (RTE_ETH_RSS_IP). */
   16783         [ #  # ]:          0 :         origin->types = !rss->types ? RTE_ETH_RSS_IP : rss->types;
   16784                 :            :         /* NULL RSS key indicates default RSS key. */
   16785         [ #  # ]:          0 :         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   16786                 :          0 :         memcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   16787                 :          0 :         origin->key = &shared_rss->key[0];
   16788                 :          0 :         origin->key_len = MLX5_RSS_HASH_KEY_LEN;
   16789                 :          0 :         origin->queue = rss->queue;
   16790                 :          0 :         origin->queue_num = rss->queue_num;
   16791         [ #  # ]:          0 :         if (__flow_dv_action_rss_setup(dev, idx, shared_rss, error))
   16792                 :          0 :                 goto error_rss_init;
   16793                 :            :         /* Update queue with indirect table queue memoyr. */
   16794                 :          0 :         origin->queue = shared_rss->ind_tbl->queues;
   16795                 :            :         rte_spinlock_init(&shared_rss->action_rss_sl);
   16796                 :          0 :         rte_atomic_fetch_add_explicit(&shared_rss->refcnt, 1, rte_memory_order_relaxed);
   16797                 :          0 :         rte_spinlock_lock(&priv->shared_act_sl);
   16798   [ #  #  #  # ]:          0 :         ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16799                 :            :                      &priv->rss_shared_actions, idx, shared_rss, next);
   16800                 :            :         rte_spinlock_unlock(&priv->shared_act_sl);
   16801                 :          0 :         return idx;
   16802                 :          0 : error_rss_init:
   16803         [ #  # ]:          0 :         if (shared_rss) {
   16804         [ #  # ]:          0 :                 if (shared_rss->ind_tbl)
   16805                 :          0 :                         mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl,
   16806                 :          0 :                                                    !!dev->data->dev_started);
   16807                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16808                 :            :                                 idx);
   16809                 :            :         }
   16810                 :            :         return 0;
   16811                 :            : }
   16812                 :            : 
   16813                 :            : /**
   16814                 :            :  * Destroy the shared RSS action.
   16815                 :            :  * Release related hash RX queue objects.
   16816                 :            :  *
   16817                 :            :  * @param[in] dev
   16818                 :            :  *   Pointer to the Ethernet device structure.
   16819                 :            :  * @param[in] idx
   16820                 :            :  *   The shared RSS action object ID to be removed.
   16821                 :            :  * @param[out] error
   16822                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16823                 :            :  *   error only.
   16824                 :            :  *
   16825                 :            :  * @return
   16826                 :            :  *   0 on success, otherwise negative errno value.
   16827                 :            :  */
   16828                 :            : static int
   16829                 :          0 : __flow_dv_action_rss_release(struct rte_eth_dev *dev, uint32_t idx,
   16830                 :            :                              struct rte_flow_error *error)
   16831                 :            : {
   16832                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16833                 :            :         struct mlx5_shared_action_rss *shared_rss =
   16834                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   16835                 :            :         uint32_t old_refcnt = 1;
   16836                 :            :         int remaining;
   16837                 :            : 
   16838         [ #  # ]:          0 :         if (!shared_rss)
   16839                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   16840                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   16841                 :            :                                           "invalid shared action");
   16842         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&shared_rss->refcnt, &old_refcnt,
   16843                 :            :                                          0, rte_memory_order_acquire,
   16844                 :            :                                          rte_memory_order_relaxed))
   16845                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16846                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16847                 :            :                                           NULL,
   16848                 :            :                                           "shared rss has references");
   16849                 :            :         remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
   16850         [ #  # ]:          0 :         if (remaining)
   16851                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16852                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16853                 :            :                                           NULL,
   16854                 :            :                                           "shared rss hrxq has references");
   16855                 :          0 :         remaining = mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl,
   16856                 :          0 :                                                !!dev->data->dev_started);
   16857         [ #  # ]:          0 :         if (remaining)
   16858                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16859                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16860                 :            :                                           NULL,
   16861                 :            :                                           "shared rss indirection table has"
   16862                 :            :                                           " references");
   16863                 :          0 :         rte_spinlock_lock(&priv->shared_act_sl);
   16864   [ #  #  #  #  :          0 :         ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
          #  #  #  #  #  
                      # ]
   16865                 :            :                      &priv->rss_shared_actions, idx, shared_rss, next);
   16866                 :            :         rte_spinlock_unlock(&priv->shared_act_sl);
   16867                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16868                 :            :                         idx);
   16869                 :          0 :         return 0;
   16870                 :            : }
   16871                 :            : 
   16872                 :            : /**
   16873                 :            :  * Create indirect action, lock free,
   16874                 :            :  * (mutex should be acquired by caller).
   16875                 :            :  * Dispatcher for action type specific call.
   16876                 :            :  *
   16877                 :            :  * @param[in] dev
   16878                 :            :  *   Pointer to the Ethernet device structure.
   16879                 :            :  * @param[in] conf
   16880                 :            :  *   Shared action configuration.
   16881                 :            :  * @param[in] action
   16882                 :            :  *   Action specification used to create indirect action.
   16883                 :            :  * @param[out] error
   16884                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16885                 :            :  *   error only.
   16886                 :            :  *
   16887                 :            :  * @return
   16888                 :            :  *   A valid shared action handle in case of success, NULL otherwise and
   16889                 :            :  *   rte_errno is set.
   16890                 :            :  */
   16891                 :            : struct rte_flow_action_handle *
   16892                 :          0 : flow_dv_action_create(struct rte_eth_dev *dev,
   16893                 :            :                       const struct rte_flow_indir_action_conf *conf,
   16894                 :            :                       const struct rte_flow_action *action,
   16895                 :            :                       struct rte_flow_error *err)
   16896                 :            : {
   16897                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16898                 :            :         uint32_t age_idx = 0;
   16899                 :            :         uint32_t idx = 0;
   16900                 :            :         uint32_t ret = 0;
   16901                 :            : 
   16902   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   16903                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   16904                 :          0 :                 ret = __flow_dv_action_rss_create(dev, conf, action->conf, err);
   16905                 :            :                 idx = (MLX5_INDIRECT_ACTION_TYPE_RSS <<
   16906                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | ret;
   16907                 :          0 :                 break;
   16908                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   16909                 :          0 :                 age_idx = flow_dv_aso_age_alloc(dev, err);
   16910         [ #  # ]:          0 :                 if (!age_idx) {
   16911                 :          0 :                         ret = -rte_errno;
   16912                 :          0 :                         break;
   16913                 :            :                 }
   16914                 :          0 :                 idx = (MLX5_INDIRECT_ACTION_TYPE_AGE <<
   16915                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | age_idx;
   16916                 :          0 :                 flow_dv_aso_age_params_init(dev, age_idx,
   16917                 :            :                                         ((const struct rte_flow_action_age *)
   16918                 :          0 :                                                 action->conf)->context ?
   16919                 :            :                                         ((const struct rte_flow_action_age *)
   16920                 :            :                                                 action->conf)->context :
   16921                 :          0 :                                         (void *)(uintptr_t)idx,
   16922                 :            :                                         ((const struct rte_flow_action_age *)
   16923         [ #  # ]:          0 :                                                 action->conf)->timeout);
   16924                 :            :                 ret = age_idx;
   16925                 :          0 :                 break;
   16926                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   16927                 :          0 :                 ret = flow_dv_translate_create_counter(dev, NULL, NULL, NULL);
   16928                 :          0 :                 idx = (MLX5_INDIRECT_ACTION_TYPE_COUNT <<
   16929                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | ret;
   16930                 :          0 :                 break;
   16931                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   16932                 :          0 :                 ret = flow_dv_translate_create_conntrack(dev, action->conf,
   16933                 :            :                                                          err);
   16934         [ #  # ]:          0 :                 if (!ret)
   16935                 :            :                         break;
   16936                 :          0 :                 idx = MLX5_INDIRECT_ACT_CT_GEN_IDX(PORT_ID(priv), ret);
   16937                 :          0 :                 break;
   16938                 :          0 :         default:
   16939                 :          0 :                 rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   16940                 :            :                                    NULL, "action type not supported");
   16941                 :            :                 break;
   16942                 :            :         }
   16943         [ #  # ]:          0 :         return ret ? (struct rte_flow_action_handle *)(uintptr_t)idx : NULL;
   16944                 :            : }
   16945                 :            : 
   16946                 :            : /**
   16947                 :            :  * Destroy the indirect action.
   16948                 :            :  * Release action related resources on the NIC and the memory.
   16949                 :            :  * Lock free, (mutex should be acquired by caller).
   16950                 :            :  * Dispatcher for action type specific call.
   16951                 :            :  *
   16952                 :            :  * @param[in] dev
   16953                 :            :  *   Pointer to the Ethernet device structure.
   16954                 :            :  * @param[in] handle
   16955                 :            :  *   The indirect action object handle to be removed.
   16956                 :            :  * @param[out] error
   16957                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16958                 :            :  *   error only.
   16959                 :            :  *
   16960                 :            :  * @return
   16961                 :            :  *   0 on success, otherwise negative errno value.
   16962                 :            :  */
   16963                 :            : int
   16964                 :          0 : flow_dv_action_destroy(struct rte_eth_dev *dev,
   16965                 :            :                        struct rte_flow_action_handle *handle,
   16966                 :            :                        struct rte_flow_error *error)
   16967                 :            : {
   16968                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   16969                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   16970                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   16971                 :            :         struct mlx5_flow_counter *cnt;
   16972                 :            :         uint32_t no_flow_refcnt = 1;
   16973                 :            :         int ret;
   16974                 :            : 
   16975   [ #  #  #  #  :          0 :         switch (type) {
                      # ]
   16976                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   16977                 :          0 :                 return __flow_dv_action_rss_release(dev, idx, error);
   16978                 :            :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   16979                 :            :                 cnt = flow_dv_counter_get_by_idx(dev, idx, NULL);
   16980         [ #  # ]:          0 :                 if (!rte_atomic_compare_exchange_strong_explicit(&cnt->shared_info.refcnt,
   16981                 :            :                                                  &no_flow_refcnt, 1,
   16982                 :            :                                                  rte_memory_order_acquire,
   16983                 :            :                                                  rte_memory_order_relaxed))
   16984                 :          0 :                         return rte_flow_error_set(error, EBUSY,
   16985                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   16986                 :            :                                                   NULL,
   16987                 :            :                                                   "Indirect count action has references");
   16988                 :          0 :                 flow_dv_counter_free(dev, idx);
   16989                 :          0 :                 return 0;
   16990                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   16991                 :          0 :                 ret = flow_dv_aso_age_release(dev, idx);
   16992         [ #  # ]:          0 :                 if (ret)
   16993                 :            :                         /*
   16994                 :            :                          * In this case, the last flow has a reference will
   16995                 :            :                          * actually release the age action.
   16996                 :            :                          */
   16997                 :          0 :                         DRV_LOG(DEBUG, "Indirect age action %" PRIu32 " was"
   16998                 :            :                                 " released with references %d.", idx, ret);
   16999                 :            :                 return 0;
   17000                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   17001                 :          0 :                 ret = flow_dv_aso_ct_release(dev, idx, error);
   17002         [ #  # ]:          0 :                 if (ret < 0)
   17003                 :            :                         return ret;
   17004         [ #  # ]:          0 :                 if (ret > 0)
   17005                 :          0 :                         DRV_LOG(DEBUG, "Connection tracking object %u still "
   17006                 :            :                                 "has references %d.", idx, ret);
   17007                 :            :                 return 0;
   17008                 :          0 :         default:
   17009                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17010                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17011                 :            :                                           NULL,
   17012                 :            :                                           "action type not supported");
   17013                 :            :         }
   17014                 :            : }
   17015                 :            : 
   17016                 :            : /**
   17017                 :            :  * Updates in place shared RSS action configuration.
   17018                 :            :  *
   17019                 :            :  * @param[in] dev
   17020                 :            :  *   Pointer to the Ethernet device structure.
   17021                 :            :  * @param[in] idx
   17022                 :            :  *   The shared RSS action object ID to be updated.
   17023                 :            :  * @param[in] action_conf
   17024                 :            :  *   RSS action specification used to modify *shared_rss*.
   17025                 :            :  * @param[out] error
   17026                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17027                 :            :  *   error only.
   17028                 :            :  *
   17029                 :            :  * @return
   17030                 :            :  *   0 on success, otherwise negative errno value.
   17031                 :            :  * @note: currently only support update of RSS queues.
   17032                 :            :  */
   17033                 :            : static int
   17034                 :          0 : __flow_dv_action_rss_update(struct rte_eth_dev *dev, uint32_t idx,
   17035                 :            :                             const struct rte_flow_action_rss *action_conf,
   17036                 :            :                             struct rte_flow_error *error)
   17037                 :            : {
   17038                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17039                 :            :         struct mlx5_shared_action_rss *shared_rss =
   17040                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   17041                 :            :         int ret = 0;
   17042                 :            :         void *queue = NULL;
   17043                 :            :         void *queue_i = NULL;
   17044                 :          0 :         uint32_t queue_size = action_conf->queue_num * sizeof(uint16_t);
   17045                 :          0 :         bool dev_started = !!dev->data->dev_started;
   17046                 :            : 
   17047         [ #  # ]:          0 :         if (!shared_rss)
   17048                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   17049                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17050                 :            :                                           "invalid shared action to update");
   17051         [ #  # ]:          0 :         if (priv->obj_ops.ind_table_modify == NULL)
   17052                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17053                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17054                 :            :                                           "cannot modify indirection table");
   17055                 :          0 :         queue = mlx5_malloc(MLX5_MEM_ZERO,
   17056                 :          0 :                             RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
   17057                 :            :                             0, SOCKET_ID_ANY);
   17058         [ #  # ]:          0 :         if (!queue)
   17059                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   17060                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17061                 :            :                                           NULL,
   17062                 :            :                                           "cannot allocate resource memory");
   17063                 :          0 :         memcpy(queue, action_conf->queue, queue_size);
   17064                 :            :         MLX5_ASSERT(shared_rss->ind_tbl);
   17065                 :          0 :         rte_spinlock_lock(&shared_rss->action_rss_sl);
   17066                 :          0 :         queue_i = shared_rss->ind_tbl->queues;
   17067                 :          0 :         ret = mlx5_ind_table_obj_modify(dev, shared_rss->ind_tbl,
   17068                 :          0 :                                         queue, action_conf->queue_num,
   17069                 :            :                                         true /* standalone */,
   17070                 :            :                                         dev_started /* ref_new_qs */,
   17071                 :            :                                         dev_started /* deref_old_qs */);
   17072         [ #  # ]:          0 :         if (ret) {
   17073                 :          0 :                 ret = rte_flow_error_set(error, rte_errno,
   17074                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17075                 :            :                                           "cannot update indirection table");
   17076                 :            :         } else {
   17077                 :            :                 /* Restore the queue to indirect table internal queue. */
   17078                 :            :                 memcpy(queue_i, queue, queue_size);
   17079                 :          0 :                 shared_rss->ind_tbl->queues = queue_i;
   17080                 :          0 :                 shared_rss->origin.queue_num = action_conf->queue_num;
   17081                 :            :         }
   17082                 :          0 :         mlx5_free(queue);
   17083                 :            :         rte_spinlock_unlock(&shared_rss->action_rss_sl);
   17084                 :          0 :         return ret;
   17085                 :            : }
   17086                 :            : 
   17087                 :            : /*
   17088                 :            :  * Updates in place conntrack context or direction.
   17089                 :            :  * Context update should be synchronized.
   17090                 :            :  *
   17091                 :            :  * @param[in] dev
   17092                 :            :  *   Pointer to the Ethernet device structure.
   17093                 :            :  * @param[in] idx
   17094                 :            :  *   The conntrack object ID to be updated.
   17095                 :            :  * @param[in] update
   17096                 :            :  *   Pointer to the structure of information to update.
   17097                 :            :  * @param[out] error
   17098                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17099                 :            :  *   error only.
   17100                 :            :  *
   17101                 :            :  * @return
   17102                 :            :  *   0 on success, otherwise negative errno value.
   17103                 :            :  */
   17104                 :            : static int
   17105                 :          0 : __flow_dv_action_ct_update(struct rte_eth_dev *dev, uint32_t idx,
   17106                 :            :                            const struct rte_flow_modify_conntrack *update,
   17107                 :            :                            struct rte_flow_error *error)
   17108                 :            : {
   17109                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17110                 :            :         struct mlx5_aso_ct_action *ct;
   17111                 :            :         const struct rte_flow_action_conntrack *new_prf;
   17112                 :            :         int ret = 0;
   17113                 :          0 :         uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(idx);
   17114                 :            :         uint32_t dev_idx;
   17115                 :            : 
   17116         [ #  # ]:          0 :         if (PORT_ID(priv) != owner)
   17117                 :          0 :                 return rte_flow_error_set(error, EACCES,
   17118                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17119                 :            :                                           NULL,
   17120                 :            :                                           "CT object owned by another port");
   17121                 :          0 :         dev_idx = MLX5_INDIRECT_ACT_CT_GET_IDX(idx);
   17122                 :          0 :         ct = flow_aso_ct_get_by_dev_idx(dev, dev_idx);
   17123         [ #  # ]:          0 :         if (!ct->refcnt)
   17124                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   17125                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17126                 :            :                                           NULL,
   17127                 :            :                                           "CT object is inactive");
   17128                 :          0 :         new_prf = &update->new_ct;
   17129         [ #  # ]:          0 :         if (update->direction)
   17130                 :          0 :                 ct->is_original = !!new_prf->is_original_dir;
   17131         [ #  # ]:          0 :         if (update->state) {
   17132                 :            :                 /* Only validate the profile when it needs to be updated. */
   17133                 :          0 :                 ret = mlx5_validate_action_ct(dev, new_prf, error);
   17134         [ #  # ]:          0 :                 if (ret)
   17135                 :            :                         return ret;
   17136                 :          0 :                 ret = mlx5_aso_ct_update_by_wqe(priv->sh, MLX5_HW_INV_QUEUE,
   17137                 :            :                                                 ct, new_prf, NULL, true);
   17138         [ #  # ]:          0 :                 if (ret)
   17139                 :          0 :                         return rte_flow_error_set(error, EIO,
   17140                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17141                 :            :                                         NULL,
   17142                 :            :                                         "Failed to send CT context update WQE");
   17143                 :            :                 /* Block until ready or a failure, default is asynchronous. */
   17144                 :          0 :                 ret = mlx5_aso_ct_available(priv->sh, MLX5_HW_INV_QUEUE, ct);
   17145         [ #  # ]:          0 :                 if (ret)
   17146                 :          0 :                         rte_flow_error_set(error, rte_errno,
   17147                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17148                 :            :                                            NULL,
   17149                 :            :                                            "Timeout to get the CT update");
   17150                 :            :         }
   17151                 :            :         return ret;
   17152                 :            : }
   17153                 :            : 
   17154                 :            : /**
   17155                 :            :  * Updates in place shared action configuration, lock free,
   17156                 :            :  * (mutex should be acquired by caller).
   17157                 :            :  *
   17158                 :            :  * @param[in] dev
   17159                 :            :  *   Pointer to the Ethernet device structure.
   17160                 :            :  * @param[in] handle
   17161                 :            :  *   The indirect action object handle to be updated.
   17162                 :            :  * @param[in] update
   17163                 :            :  *   Action specification used to modify the action pointed by *handle*.
   17164                 :            :  *   *update* could be of same type with the action pointed by the *handle*
   17165                 :            :  *   handle argument, or some other structures like a wrapper, depending on
   17166                 :            :  *   the indirect action type.
   17167                 :            :  * @param[out] error
   17168                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17169                 :            :  *   error only.
   17170                 :            :  *
   17171                 :            :  * @return
   17172                 :            :  *   0 on success, otherwise negative errno value.
   17173                 :            :  */
   17174                 :            : int
   17175                 :          0 : flow_dv_action_update(struct rte_eth_dev *dev,
   17176                 :            :                         struct rte_flow_action_handle *handle,
   17177                 :            :                         const void *update,
   17178                 :            :                         struct rte_flow_error *err)
   17179                 :            : {
   17180                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   17181                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   17182                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   17183                 :            :         const void *action_conf;
   17184                 :            : 
   17185      [ #  #  # ]:          0 :         switch (type) {
   17186                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   17187                 :          0 :                 action_conf = ((const struct rte_flow_action *)update)->conf;
   17188                 :          0 :                 return __flow_dv_action_rss_update(dev, idx, action_conf, err);
   17189                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   17190                 :          0 :                 return __flow_dv_action_ct_update(dev, idx, update, err);
   17191                 :          0 :         default:
   17192                 :          0 :                 return rte_flow_error_set(err, ENOTSUP,
   17193                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17194                 :            :                                           NULL,
   17195                 :            :                                           "action type update not supported");
   17196                 :            :         }
   17197                 :            : }
   17198                 :            : 
   17199                 :            : /**
   17200                 :            :  * Destroy the meter sub policy table rules.
   17201                 :            :  * Lock free, (mutex should be acquired by caller).
   17202                 :            :  *
   17203                 :            :  * @param[in] dev
   17204                 :            :  *   Pointer to Ethernet device.
   17205                 :            :  * @param[in] sub_policy
   17206                 :            :  *   Pointer to meter sub policy table.
   17207                 :            :  */
   17208                 :            : static void
   17209                 :          0 : __flow_dv_destroy_sub_policy_rules(struct rte_eth_dev *dev,
   17210                 :            :                              struct mlx5_flow_meter_sub_policy *sub_policy)
   17211                 :            : {
   17212                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17213                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   17214                 :          0 :         struct mlx5_flow_meter_policy *policy = sub_policy->main_policy;
   17215                 :            :         struct mlx5_flow_meter_info *next_fm;
   17216                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   17217                 :            :         void *tmp;
   17218                 :            :         uint32_t i;
   17219                 :            : 
   17220         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   17221                 :            :                 next_fm = NULL;
   17222         [ #  # ]:          0 :                 if (i <= RTE_COLOR_YELLOW && policy &&
   17223         [ #  # ]:          0 :                     policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR)
   17224                 :          0 :                         next_fm = mlx5_flow_meter_find(priv,
   17225                 :            :                                         policy->act_cnt[i].next_mtr_id, NULL);
   17226         [ #  # ]:          0 :                 RTE_TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
   17227                 :            :                                    next_port, tmp) {
   17228                 :          0 :                         claim_zero(mlx5_flow_os_destroy_flow(color_rule->rule));
   17229                 :          0 :                         tbl = container_of(color_rule->matcher->tbl,
   17230                 :            :                                            typeof(*tbl), tbl);
   17231                 :          0 :                         mlx5_list_unregister(tbl->matchers,
   17232                 :            :                                              &color_rule->matcher->entry);
   17233         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[i],
   17234                 :            :                                      color_rule, next_port);
   17235                 :          0 :                         mlx5_free(color_rule);
   17236         [ #  # ]:          0 :                         if (next_fm)
   17237                 :          0 :                                 mlx5_flow_meter_detach(priv, next_fm);
   17238                 :            :                 }
   17239                 :            :         }
   17240         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   17241         [ #  # ]:          0 :                 if (sub_policy->rix_hrxq[i]) {
   17242   [ #  #  #  # ]:          0 :                         if (policy && !policy->is_hierarchy)
   17243                 :          0 :                                 mlx5_hrxq_release(dev, sub_policy->rix_hrxq[i]);
   17244                 :          0 :                         sub_policy->rix_hrxq[i] = 0;
   17245                 :            :                 }
   17246         [ #  # ]:          0 :                 if (sub_policy->jump_tbl[i]) {
   17247                 :          0 :                         flow_dv_tbl_resource_release(MLX5_SH(dev),
   17248                 :            :                                                      sub_policy->jump_tbl[i]);
   17249                 :          0 :                         sub_policy->jump_tbl[i] = NULL;
   17250                 :            :                 }
   17251                 :            :         }
   17252         [ #  # ]:          0 :         if (sub_policy->tbl_rsc) {
   17253                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   17254                 :            :                                              sub_policy->tbl_rsc);
   17255                 :          0 :                 sub_policy->tbl_rsc = NULL;
   17256                 :            :         }
   17257                 :          0 : }
   17258                 :            : 
   17259                 :            : /**
   17260                 :            :  * Destroy policy rules, lock free,
   17261                 :            :  * (mutex should be acquired by caller).
   17262                 :            :  * Dispatcher for action type specific call.
   17263                 :            :  *
   17264                 :            :  * @param[in] dev
   17265                 :            :  *   Pointer to the Ethernet device structure.
   17266                 :            :  * @param[in] mtr_policy
   17267                 :            :  *   Meter policy struct.
   17268                 :            :  */
   17269                 :            : static void
   17270                 :          0 : flow_dv_destroy_policy_rules(struct rte_eth_dev *dev,
   17271                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
   17272                 :            : {
   17273                 :            :         uint32_t i, j;
   17274                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   17275                 :            :         uint16_t sub_policy_num;
   17276                 :            : 
   17277         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   17278                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   17279                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   17280                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   17281         [ #  # ]:          0 :                 for (j = 0; j < sub_policy_num; j++) {
   17282                 :          0 :                         sub_policy = mtr_policy->sub_policys[i][j];
   17283         [ #  # ]:          0 :                         if (sub_policy)
   17284                 :          0 :                                 __flow_dv_destroy_sub_policy_rules(dev,
   17285                 :            :                                                                    sub_policy);
   17286                 :            :                 }
   17287                 :            :         }
   17288                 :          0 : }
   17289                 :            : 
   17290                 :            : /**
   17291                 :            :  * Destroy policy action, lock free,
   17292                 :            :  * (mutex should be acquired by caller).
   17293                 :            :  * Dispatcher for action type specific call.
   17294                 :            :  *
   17295                 :            :  * @param[in] dev
   17296                 :            :  *   Pointer to the Ethernet device structure.
   17297                 :            :  * @param[in] mtr_policy
   17298                 :            :  *   Meter policy struct.
   17299                 :            :  */
   17300                 :            : static void
   17301                 :          0 : flow_dv_destroy_mtr_policy_acts(struct rte_eth_dev *dev,
   17302                 :            :                       struct mlx5_flow_meter_policy *mtr_policy)
   17303                 :            : {
   17304                 :            :         struct rte_flow_action *rss_action;
   17305                 :            :         struct mlx5_flow_handle dev_handle;
   17306                 :            :         uint32_t i, j;
   17307                 :            : 
   17308         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   17309         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].rix_mark) {
   17310                 :          0 :                         flow_dv_tag_release(dev,
   17311                 :            :                                 mtr_policy->act_cnt[i].rix_mark);
   17312                 :          0 :                         mtr_policy->act_cnt[i].rix_mark = 0;
   17313                 :            :                 }
   17314         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].modify_hdr) {
   17315                 :            :                         dev_handle.dvh.modify_hdr =
   17316                 :            :                                 mtr_policy->act_cnt[i].modify_hdr;
   17317                 :            :                         flow_dv_modify_hdr_resource_release(dev, &dev_handle);
   17318                 :            :                 }
   17319   [ #  #  #  # ]:          0 :                 switch (mtr_policy->act_cnt[i].fate_action) {
   17320                 :          0 :                 case MLX5_FLOW_FATE_SHARED_RSS:
   17321                 :          0 :                         rss_action = mtr_policy->act_cnt[i].rss;
   17322                 :          0 :                         mlx5_free(rss_action);
   17323                 :          0 :                         break;
   17324                 :          0 :                 case MLX5_FLOW_FATE_PORT_ID:
   17325         [ #  # ]:          0 :                         if (mtr_policy->act_cnt[i].rix_port_id_action) {
   17326                 :          0 :                                 flow_dv_port_id_action_resource_release(dev,
   17327                 :            :                                 mtr_policy->act_cnt[i].rix_port_id_action);
   17328                 :          0 :                                 mtr_policy->act_cnt[i].rix_port_id_action = 0;
   17329                 :            :                         }
   17330                 :            :                         break;
   17331                 :            :                 case MLX5_FLOW_FATE_DROP:
   17332                 :            :                 case MLX5_FLOW_FATE_JUMP:
   17333         [ #  # ]:          0 :                         for (j = 0; j < MLX5_MTR_DOMAIN_MAX; j++)
   17334                 :          0 :                                 mtr_policy->act_cnt[i].dr_jump_action[j] =
   17335                 :            :                                                 NULL;
   17336                 :            :                         break;
   17337                 :            :                 default:
   17338                 :            :                         /*Queue action do nothing*/
   17339                 :            :                         break;
   17340                 :            :                 }
   17341                 :            :         }
   17342         [ #  # ]:          0 :         for (j = 0; j < MLX5_MTR_DOMAIN_MAX; j++)
   17343                 :          0 :                 mtr_policy->dr_drop_action[j] = NULL;
   17344                 :          0 : }
   17345                 :            : 
   17346                 :            : /**
   17347                 :            :  * Create yellow action for color aware meter.
   17348                 :            :  *
   17349                 :            :  * @param[in] dev
   17350                 :            :  *   Pointer to the Ethernet device structure.
   17351                 :            :  * @param[in] fm
   17352                 :            :  *   Meter information table.
   17353                 :            :  * @param[out] error
   17354                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17355                 :            :  *   error only.
   17356                 :            :  *
   17357                 :            :  * @return
   17358                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   17359                 :            :  */
   17360                 :            : static int
   17361                 :          0 : __flow_dv_create_mtr_yellow_action(struct rte_eth_dev *dev,
   17362                 :            :                                    struct mlx5_flow_meter_info *fm,
   17363                 :            :                                    struct rte_mtr_error *error)
   17364                 :            : {
   17365                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
   17366                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17367                 :            :         struct rte_flow_error flow_err;
   17368                 :            :         struct mlx5_aso_mtr *aso_mtr;
   17369                 :            :         struct mlx5_aso_mtr_pool *pool;
   17370                 :            :         uint8_t reg_id;
   17371                 :            : 
   17372                 :          0 :         aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
   17373                 :          0 :         pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool, mtrs[aso_mtr->offset]);
   17374                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &flow_err);
   17375                 :          0 :         fm->meter_action_y =
   17376                 :          0 :                 mlx5_glue->dv_create_flow_action_aso(priv->sh->rx_domain,
   17377                 :          0 :                                                      pool->devx_obj->obj,
   17378                 :            :                                                      aso_mtr->offset,
   17379                 :            :                                                      (1 << MLX5_FLOW_COLOR_YELLOW),
   17380                 :          0 :                                                      reg_id - REG_C_0);
   17381                 :            : #else
   17382                 :            :         RTE_SET_USED(dev);
   17383                 :            : #endif
   17384         [ #  # ]:          0 :         if (!fm->meter_action_y) {
   17385                 :          0 :                 return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17386                 :            :                                           "Fail to create yellow meter action.");
   17387                 :            :         }
   17388                 :            :         return 0;
   17389                 :            : }
   17390                 :            : 
   17391                 :            : /**
   17392                 :            :  * Create policy action per domain, lock free,
   17393                 :            :  * (mutex should be acquired by caller).
   17394                 :            :  * Dispatcher for action type specific call.
   17395                 :            :  *
   17396                 :            :  * @param[in] dev
   17397                 :            :  *   Pointer to the Ethernet device structure.
   17398                 :            :  * @param[in] mtr_policy
   17399                 :            :  *   Meter policy struct.
   17400                 :            :  * @param[in] action
   17401                 :            :  *   Action specification used to create meter actions.
   17402                 :            :  * @param[in] attr
   17403                 :            :  *   Pointer to the flow attributes.
   17404                 :            :  * @param[out] error
   17405                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17406                 :            :  *   error only.
   17407                 :            :  *
   17408                 :            :  * @return
   17409                 :            :  *   0 on success, otherwise negative errno value.
   17410                 :            :  */
   17411                 :            : static int
   17412                 :          0 : __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev,
   17413                 :            :                         struct mlx5_flow_meter_policy *mtr_policy,
   17414                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
   17415                 :            :                         struct rte_flow_attr *attr,
   17416                 :            :                         enum mlx5_meter_domain domain,
   17417                 :            :                         struct rte_mtr_error *error)
   17418                 :            : {
   17419                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17420                 :            :         struct rte_flow_error flow_err;
   17421                 :            :         const struct rte_flow_action *act;
   17422                 :            :         uint64_t action_flags;
   17423                 :            :         struct mlx5_flow_handle dh;
   17424                 :            :         struct mlx5_flow dev_flow;
   17425                 :            :         struct mlx5_flow_dv_port_id_action_resource port_id_action;
   17426                 :            :         int i, ret;
   17427                 :            :         uint8_t egress, transfer;
   17428                 :            :         struct mlx5_meter_policy_action_container *act_cnt = NULL;
   17429                 :            :         union {
   17430                 :            :                 struct mlx5_flow_dv_modify_hdr_resource res;
   17431                 :            :                 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   17432                 :            :                             sizeof(struct mlx5_modification_cmd) *
   17433                 :            :                             (MLX5_MAX_MODIFY_NUM + 1)];
   17434                 :            :         } mhdr_dummy;
   17435                 :            :         struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
   17436                 :            : 
   17437                 :          0 :         egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   17438         [ #  # ]:          0 :         transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   17439                 :            :         memset(&dh, 0, sizeof(struct mlx5_flow_handle));
   17440                 :            :         memset(&dev_flow, 0, sizeof(struct mlx5_flow));
   17441                 :            :         memset(&port_id_action, 0,
   17442                 :            :                sizeof(struct mlx5_flow_dv_port_id_action_resource));
   17443                 :            :         memset(mhdr_res, 0, sizeof(*mhdr_res));
   17444         [ #  # ]:          0 :         mhdr_res->ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
   17445                 :            :                                        (egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   17446                 :            :                                         MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
   17447                 :          0 :         dev_flow.handle = &dh;
   17448                 :          0 :         dev_flow.dv.port_id_action = &port_id_action;
   17449                 :          0 :         dev_flow.external = true;
   17450         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   17451         [ #  # ]:          0 :                 if (i < MLX5_MTR_RTE_COLORS)
   17452                 :          0 :                         act_cnt = &mtr_policy->act_cnt[i];
   17453                 :            :                 /* Skip the color policy actions creation. */
   17454   [ #  #  #  #  :          0 :                 if ((i == RTE_COLOR_YELLOW && mtr_policy->skip_y) ||
                   #  # ]
   17455         [ #  # ]:          0 :                     (i == RTE_COLOR_GREEN && mtr_policy->skip_g))
   17456                 :          0 :                         continue;
   17457                 :            :                 action_flags = 0;
   17458                 :          0 :                 for (act = actions[i];
   17459   [ #  #  #  # ]:          0 :                      act && act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
   17460   [ #  #  #  #  :          0 :                         switch (act->type) {
          #  #  #  #  #  
                      # ]
   17461                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MARK:
   17462                 :            :                         {
   17463                 :            :                                 uint32_t tag_be = mlx5_flow_mark_set
   17464                 :            :                                         (((const struct rte_flow_action_mark *)
   17465         [ #  # ]:          0 :                                         (act->conf))->id);
   17466                 :            : 
   17467         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17468                 :          0 :                                         return -rte_mtr_error_set(error,
   17469                 :            :                                           ENOTSUP,
   17470                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17471                 :            :                                           NULL,
   17472                 :            :                                           "cannot create policy "
   17473                 :            :                                           "mark action for this color");
   17474         [ #  # ]:          0 :                                 if (flow_dv_tag_resource_register(dev, tag_be,
   17475                 :            :                                                   &dev_flow, &flow_err))
   17476                 :          0 :                                         return -rte_mtr_error_set(error,
   17477                 :            :                                         ENOTSUP,
   17478                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17479                 :            :                                         NULL,
   17480                 :            :                                         "cannot setup policy mark action");
   17481                 :            :                                 MLX5_ASSERT(dev_flow.dv.tag_resource);
   17482                 :          0 :                                 act_cnt->rix_mark =
   17483                 :          0 :                                         dev_flow.handle->dvh.rix_tag;
   17484                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK;
   17485                 :          0 :                                 mtr_policy->mark = 1;
   17486                 :          0 :                                 break;
   17487                 :            :                         }
   17488                 :          0 :                         case RTE_FLOW_ACTION_TYPE_SET_TAG:
   17489         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17490                 :          0 :                                         return -rte_mtr_error_set(error,
   17491                 :            :                                           ENOTSUP,
   17492                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17493                 :            :                                           NULL,
   17494                 :            :                                           "cannot create policy "
   17495                 :            :                                           "set tag action for this color");
   17496         [ #  # ]:          0 :                                 if (flow_dv_convert_action_set_tag
   17497                 :            :                                 (dev, mhdr_res,
   17498                 :            :                                 (const struct rte_flow_action_set_tag *)
   17499                 :          0 :                                 act->conf,  &flow_err))
   17500                 :          0 :                                         return -rte_mtr_error_set(error,
   17501                 :            :                                         ENOTSUP,
   17502                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17503                 :            :                                         NULL, "cannot convert policy "
   17504                 :            :                                         "set tag action");
   17505         [ #  # ]:          0 :                                 if (!mhdr_res->actions_num)
   17506                 :          0 :                                         return -rte_mtr_error_set(error,
   17507                 :            :                                         ENOTSUP,
   17508                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17509                 :            :                                         NULL, "cannot find policy "
   17510                 :            :                                         "set tag action");
   17511                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   17512                 :          0 :                                 break;
   17513                 :          0 :                         case RTE_FLOW_ACTION_TYPE_DROP:
   17514                 :            :                         {
   17515                 :          0 :                                 struct mlx5_flow_mtr_mng *mtrmng =
   17516                 :          0 :                                                 priv->sh->mtrmng;
   17517                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl_data;
   17518                 :            : 
   17519                 :            :                                 /*
   17520                 :            :                                  * Create the drop table with
   17521                 :            :                                  * METER DROP level.
   17522                 :            :                                  */
   17523         [ #  # ]:          0 :                                 if (!mtrmng->drop_tbl[domain]) {
   17524                 :          0 :                                         mtrmng->drop_tbl[domain] =
   17525                 :          0 :                                         flow_dv_tbl_resource_get(dev,
   17526                 :            :                                         MLX5_FLOW_TABLE_LEVEL_METER,
   17527                 :            :                                         egress, transfer, false, NULL, 0,
   17528                 :            :                                         0, MLX5_MTR_TABLE_ID_DROP, &flow_err);
   17529         [ #  # ]:          0 :                                         if (!mtrmng->drop_tbl[domain])
   17530                 :          0 :                                                 return -rte_mtr_error_set
   17531                 :            :                                         (error, ENOTSUP,
   17532                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17533                 :            :                                         NULL,
   17534                 :            :                                         "Failed to create meter drop table");
   17535                 :            :                                 }
   17536                 :          0 :                                 tbl_data = container_of
   17537                 :            :                                 (mtrmng->drop_tbl[domain],
   17538                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17539         [ #  # ]:          0 :                                 if (i < MLX5_MTR_RTE_COLORS) {
   17540                 :          0 :                                         act_cnt->dr_jump_action[domain] =
   17541                 :          0 :                                                 tbl_data->jump.action;
   17542                 :          0 :                                         act_cnt->fate_action =
   17543                 :            :                                                 MLX5_FLOW_FATE_DROP;
   17544                 :            :                                 }
   17545         [ #  # ]:          0 :                                 if (i == RTE_COLOR_RED)
   17546                 :          0 :                                         mtr_policy->dr_drop_action[domain] =
   17547                 :          0 :                                                 tbl_data->jump.action;
   17548                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_DROP;
   17549                 :          0 :                                 break;
   17550                 :            :                         }
   17551                 :          0 :                         case RTE_FLOW_ACTION_TYPE_QUEUE:
   17552                 :            :                         {
   17553         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17554                 :          0 :                                         return -rte_mtr_error_set(error,
   17555                 :            :                                         ENOTSUP,
   17556                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17557                 :            :                                         NULL, "cannot create policy "
   17558                 :            :                                         "fate queue for this color");
   17559                 :          0 :                                 act_cnt->queue =
   17560                 :            :                                 ((const struct rte_flow_action_queue *)
   17561                 :          0 :                                         (act->conf))->index;
   17562                 :          0 :                                 act_cnt->fate_action =
   17563                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   17564                 :          0 :                                 dev_flow.handle->fate_action =
   17565                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   17566                 :          0 :                                 mtr_policy->is_queue = 1;
   17567                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_QUEUE;
   17568                 :          0 :                                 break;
   17569                 :            :                         }
   17570                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RSS:
   17571                 :            :                         {
   17572                 :            :                                 int rss_size;
   17573                 :            : 
   17574         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17575                 :          0 :                                         return -rte_mtr_error_set(error,
   17576                 :            :                                           ENOTSUP,
   17577                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17578                 :            :                                           NULL,
   17579                 :            :                                           "cannot create policy "
   17580                 :            :                                           "rss action for this color");
   17581                 :            :                                 /*
   17582                 :            :                                  * Save RSS conf into policy struct
   17583                 :            :                                  * for translate stage.
   17584                 :            :                                  */
   17585                 :          0 :                                 rss_size = (int)rte_flow_conv
   17586                 :            :                                         (RTE_FLOW_CONV_OP_ACTION,
   17587                 :            :                                         NULL, 0, act, &flow_err);
   17588         [ #  # ]:          0 :                                 if (rss_size <= 0)
   17589                 :          0 :                                         return -rte_mtr_error_set(error,
   17590                 :            :                                           ENOTSUP,
   17591                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17592                 :            :                                           NULL, "Get the wrong "
   17593                 :            :                                           "rss action struct size");
   17594                 :          0 :                                 act_cnt->rss = mlx5_malloc(MLX5_MEM_ZERO,
   17595                 :            :                                                 rss_size, 0, SOCKET_ID_ANY);
   17596         [ #  # ]:          0 :                                 if (!act_cnt->rss)
   17597                 :          0 :                                         return -rte_mtr_error_set(error,
   17598                 :            :                                           ENOTSUP,
   17599                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17600                 :            :                                           NULL,
   17601                 :            :                                           "Fail to malloc rss action memory");
   17602                 :          0 :                                 ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTION,
   17603                 :            :                                         act_cnt->rss, rss_size,
   17604                 :            :                                         act, &flow_err);
   17605         [ #  # ]:          0 :                                 if (ret < 0)
   17606                 :          0 :                                         return -rte_mtr_error_set(error,
   17607                 :            :                                           ENOTSUP,
   17608                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17609                 :            :                                           NULL, "Fail to save "
   17610                 :            :                                           "rss action into policy struct");
   17611                 :          0 :                                 act_cnt->fate_action =
   17612                 :            :                                         MLX5_FLOW_FATE_SHARED_RSS;
   17613                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_RSS;
   17614                 :          0 :                                 break;
   17615                 :            :                         }
   17616                 :          0 :                         case RTE_FLOW_ACTION_TYPE_PORT_ID:
   17617                 :            :                         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   17618                 :            :                         {
   17619                 :            :                                 struct mlx5_flow_dv_port_id_action_resource
   17620                 :            :                                         port_id_resource;
   17621                 :          0 :                                 uint32_t port_id = 0;
   17622                 :            : 
   17623         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17624                 :          0 :                                         return -rte_mtr_error_set(error,
   17625                 :            :                                         ENOTSUP,
   17626                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17627                 :            :                                         NULL, "cannot create policy "
   17628                 :            :                                         "port action for this color");
   17629                 :            :                                 memset(&port_id_resource, 0,
   17630                 :            :                                         sizeof(port_id_resource));
   17631         [ #  # ]:          0 :                                 if (flow_dv_translate_action_port_id(dev, act,
   17632                 :            :                                                 &port_id, &flow_err))
   17633                 :          0 :                                         return -rte_mtr_error_set(error,
   17634                 :            :                                         ENOTSUP,
   17635                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17636                 :            :                                         NULL, "cannot translate "
   17637                 :            :                                         "policy port action");
   17638                 :          0 :                                 port_id_resource.port_id = port_id;
   17639         [ #  # ]:          0 :                                 if (flow_dv_port_id_action_resource_register
   17640                 :            :                                         (dev, &port_id_resource,
   17641                 :            :                                         &dev_flow, &flow_err))
   17642                 :          0 :                                         return -rte_mtr_error_set(error,
   17643                 :            :                                         ENOTSUP,
   17644                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17645                 :            :                                         NULL, "cannot setup "
   17646                 :            :                                         "policy port action");
   17647                 :          0 :                                 act_cnt->rix_port_id_action =
   17648                 :          0 :                                         dev_flow.handle->rix_port_id_action;
   17649                 :          0 :                                 act_cnt->fate_action =
   17650                 :            :                                         MLX5_FLOW_FATE_PORT_ID;
   17651                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   17652                 :          0 :                                 break;
   17653                 :            :                         }
   17654                 :          0 :                         case RTE_FLOW_ACTION_TYPE_JUMP:
   17655                 :            :                         {
   17656                 :            :                                 uint32_t jump_group = 0;
   17657                 :          0 :                                 uint32_t table = 0;
   17658                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl_data;
   17659                 :          0 :                                 struct flow_grp_info grp_info = {
   17660                 :          0 :                                         .external = !!dev_flow.external,
   17661                 :            :                                         .transfer = !!transfer,
   17662                 :          0 :                                         .fdb_def_rule = !!priv->fdb_def_rule,
   17663                 :            :                                         .std_tbl_fix = 0,
   17664                 :          0 :                                         .skip_scale = dev_flow.skip_scale &
   17665                 :            :                                         (1 << MLX5_SCALE_FLOW_GROUP_BIT),
   17666                 :            :                                 };
   17667                 :          0 :                                 struct mlx5_flow_meter_sub_policy *sub_policy =
   17668                 :          0 :                                         mtr_policy->sub_policys[domain][0];
   17669                 :            : 
   17670         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17671                 :          0 :                                         return -rte_mtr_error_set(error,
   17672                 :            :                                           ENOTSUP,
   17673                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17674                 :            :                                           NULL,
   17675                 :            :                                           "cannot create policy "
   17676                 :            :                                           "jump action for this color");
   17677                 :          0 :                                 jump_group =
   17678                 :            :                                 ((const struct rte_flow_action_jump *)
   17679                 :          0 :                                                         act->conf)->group;
   17680         [ #  # ]:          0 :                                 if (mlx5_flow_group_to_table(dev, NULL,
   17681                 :            :                                                        jump_group,
   17682                 :            :                                                        &table,
   17683                 :            :                                                        &grp_info, &flow_err))
   17684                 :          0 :                                         return -rte_mtr_error_set(error,
   17685                 :            :                                         ENOTSUP,
   17686                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17687                 :            :                                         NULL, "cannot setup "
   17688                 :            :                                         "policy jump action");
   17689                 :          0 :                                 sub_policy->jump_tbl[i] =
   17690                 :          0 :                                 flow_dv_tbl_resource_get(dev,
   17691                 :            :                                         table, egress,
   17692                 :            :                                         transfer,
   17693                 :            :                                         !!dev_flow.external,
   17694                 :            :                                         NULL, jump_group, 0,
   17695                 :            :                                         0, &flow_err);
   17696                 :            :                                 if
   17697         [ #  # ]:          0 :                                 (!sub_policy->jump_tbl[i])
   17698                 :          0 :                                         return  -rte_mtr_error_set(error,
   17699                 :            :                                         ENOTSUP,
   17700                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17701                 :            :                                         NULL, "cannot create jump action.");
   17702                 :          0 :                                 tbl_data = container_of
   17703                 :            :                                 (sub_policy->jump_tbl[i],
   17704                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17705                 :          0 :                                 act_cnt->dr_jump_action[domain] =
   17706                 :          0 :                                         tbl_data->jump.action;
   17707                 :          0 :                                 act_cnt->fate_action =
   17708                 :            :                                         MLX5_FLOW_FATE_JUMP;
   17709                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_JUMP;
   17710                 :          0 :                                 break;
   17711                 :            :                         }
   17712                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   17713                 :            :                         {
   17714         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17715                 :          0 :                                         return -rte_mtr_error_set(error,
   17716                 :            :                                           ENOTSUP,
   17717                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17718                 :            :                                           NULL,
   17719                 :            :                                           "cannot create policy modify field for this color");
   17720         [ #  # ]:          0 :                                 if (flow_dv_convert_action_modify_field
   17721                 :            :                                         (dev, mhdr_res, act, attr, &flow_err))
   17722                 :          0 :                                         return -rte_mtr_error_set(error,
   17723                 :            :                                         ENOTSUP,
   17724                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17725                 :            :                                         NULL, "cannot setup policy modify field action");
   17726         [ #  # ]:          0 :                                 if (!mhdr_res->actions_num)
   17727                 :          0 :                                         return -rte_mtr_error_set(error,
   17728                 :            :                                         ENOTSUP,
   17729                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17730                 :            :                                         NULL, "cannot find policy modify field action");
   17731                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   17732                 :          0 :                                 break;
   17733                 :            :                         }
   17734                 :            :                         /*
   17735                 :            :                          * No need to check meter hierarchy for R colors
   17736                 :            :                          * here since it is done in the validation stage.
   17737                 :            :                          */
   17738                 :          0 :                         case RTE_FLOW_ACTION_TYPE_METER:
   17739                 :            :                         {
   17740                 :            :                                 const struct rte_flow_action_meter *mtr;
   17741                 :            :                                 struct mlx5_flow_meter_info *next_fm;
   17742                 :            :                                 struct mlx5_flow_meter_policy *next_policy;
   17743                 :            :                                 struct rte_flow_action tag_action;
   17744                 :            :                                 struct mlx5_rte_flow_action_set_tag set_tag;
   17745                 :          0 :                                 uint32_t next_mtr_idx = 0;
   17746                 :            : 
   17747                 :          0 :                                 mtr = act->conf;
   17748                 :          0 :                                 next_fm = mlx5_flow_meter_find(priv,
   17749                 :          0 :                                                         mtr->mtr_id,
   17750                 :            :                                                         &next_mtr_idx);
   17751         [ #  # ]:          0 :                                 if (!next_fm)
   17752                 :          0 :                                         return -rte_mtr_error_set(error, EINVAL,
   17753                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17754                 :            :                                                 "Fail to find next meter.");
   17755         [ #  # ]:          0 :                                 if (next_fm->def_policy)
   17756                 :          0 :                                         return -rte_mtr_error_set(error, EINVAL,
   17757                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17758                 :            :                                 "Hierarchy only supports termination meter.");
   17759                 :          0 :                                 next_policy = mlx5_flow_meter_policy_find(dev,
   17760                 :            :                                                 next_fm->policy_id, NULL);
   17761                 :            :                                 MLX5_ASSERT(next_policy);
   17762         [ #  # ]:          0 :                                 if (next_fm->drop_cnt) {
   17763                 :          0 :                                         set_tag.id =
   17764                 :          0 :                                                 (enum modify_reg)
   17765                 :          0 :                                                 mlx5_flow_get_reg_id(dev,
   17766                 :            :                                                 MLX5_MTR_ID,
   17767                 :            :                                                 0,
   17768                 :            :                                                 (struct rte_flow_error *)error);
   17769                 :          0 :                                         set_tag.offset = (priv->mtr_reg_share ?
   17770                 :          0 :                                                 MLX5_MTR_COLOR_BITS : 0);
   17771         [ #  # ]:          0 :                                         set_tag.length = (priv->mtr_reg_share ?
   17772                 :            :                                                MLX5_MTR_IDLE_BITS_IN_COLOR_REG :
   17773                 :            :                                                MLX5_REG_BITS);
   17774                 :          0 :                                         set_tag.data = next_mtr_idx;
   17775                 :          0 :                                         tag_action.type =
   17776                 :            :                                                 (enum rte_flow_action_type)
   17777                 :            :                                                 MLX5_RTE_FLOW_ACTION_TYPE_TAG;
   17778                 :          0 :                                         tag_action.conf = &set_tag;
   17779         [ #  # ]:          0 :                                         if (flow_dv_convert_action_set_reg
   17780                 :            :                                                 (mhdr_res, &tag_action,
   17781                 :            :                                                 (struct rte_flow_error *)error))
   17782                 :          0 :                                                 return -rte_errno;
   17783                 :          0 :                                         action_flags |=
   17784                 :            :                                                 MLX5_FLOW_ACTION_SET_TAG;
   17785                 :            :                                 }
   17786   [ #  #  #  # ]:          0 :                                 if (i == RTE_COLOR_YELLOW && next_fm->color_aware &&
   17787         [ #  # ]:          0 :                                     !next_fm->meter_action_y)
   17788         [ #  # ]:          0 :                                         if (__flow_dv_create_mtr_yellow_action(dev, next_fm, error))
   17789                 :          0 :                                                 return -rte_errno;
   17790                 :          0 :                                 act_cnt->fate_action = MLX5_FLOW_FATE_MTR;
   17791                 :          0 :                                 act_cnt->next_mtr_id = next_fm->meter_id;
   17792                 :          0 :                                 act_cnt->next_sub_policy = NULL;
   17793                 :          0 :                                 mtr_policy->is_hierarchy = 1;
   17794         [ #  # ]:          0 :                                 if (next_policy->mark)
   17795                 :          0 :                                         mtr_policy->mark = 1;
   17796                 :          0 :                                 mtr_policy->hierarchy_match_port =
   17797                 :          0 :                                                         next_policy->hierarchy_match_port;
   17798                 :          0 :                                 action_flags |=
   17799                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
   17800                 :          0 :                                 break;
   17801                 :            :                         }
   17802                 :            :                         default:
   17803                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   17804                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17805                 :            :                                           NULL, "action type not supported");
   17806                 :            :                         }
   17807         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) ||
   17808                 :            :                             (action_flags & MLX5_FLOW_ACTION_MODIFY_FIELD)) {
   17809                 :            :                                 /* create modify action if needed. */
   17810                 :          0 :                                 dev_flow.dv.group = 1;
   17811         [ #  # ]:          0 :                                 if (flow_dv_modify_hdr_resource_register
   17812                 :            :                                         (dev, mhdr_res, &dev_flow, &flow_err))
   17813                 :          0 :                                         return -rte_mtr_error_set(error,
   17814                 :            :                                                 ENOTSUP,
   17815                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   17816                 :            :                                                 NULL, "cannot register policy set tag/modify field action");
   17817                 :          0 :                                 act_cnt->modify_hdr =
   17818                 :          0 :                                         dev_flow.handle->dvh.modify_hdr;
   17819                 :            :                         }
   17820                 :            :                 }
   17821                 :            :         }
   17822                 :            :         return 0;
   17823                 :            : }
   17824                 :            : 
   17825                 :            : /**
   17826                 :            :  * Create policy action per domain, lock free,
   17827                 :            :  * (mutex should be acquired by caller).
   17828                 :            :  * Dispatcher for action type specific call.
   17829                 :            :  *
   17830                 :            :  * @param[in] dev
   17831                 :            :  *   Pointer to the Ethernet device structure.
   17832                 :            :  * @param[in] mtr_policy
   17833                 :            :  *   Meter policy struct.
   17834                 :            :  * @param[in] action
   17835                 :            :  *   Action specification used to create meter actions.
   17836                 :            :  * @param[in] attr
   17837                 :            :  *   Pointer to the flow attributes.
   17838                 :            :  * @param[out] error
   17839                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17840                 :            :  *   error only.
   17841                 :            :  *
   17842                 :            :  * @return
   17843                 :            :  *   0 on success, otherwise negative errno value.
   17844                 :            :  */
   17845                 :            : static int
   17846                 :          0 : flow_dv_create_mtr_policy_acts(struct rte_eth_dev *dev,
   17847                 :            :                       struct mlx5_flow_meter_policy *mtr_policy,
   17848                 :            :                       const struct rte_flow_action *actions[RTE_COLORS],
   17849                 :            :                       struct rte_flow_attr *attr,
   17850                 :            :                       struct rte_mtr_error *error)
   17851                 :            : {
   17852                 :            :         int ret, i;
   17853                 :            :         uint16_t sub_policy_num;
   17854                 :            : 
   17855         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   17856                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   17857                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   17858                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   17859         [ #  # ]:          0 :                 if (sub_policy_num) {
   17860                 :          0 :                         ret = __flow_dv_create_domain_policy_acts(dev,
   17861                 :            :                                 mtr_policy, actions, attr,
   17862                 :            :                                 (enum mlx5_meter_domain)i, error);
   17863                 :            :                         /* Cleaning resource is done in the caller level. */
   17864         [ #  # ]:          0 :                         if (ret)
   17865                 :          0 :                                 return ret;
   17866                 :            :                 }
   17867                 :            :         }
   17868                 :            :         return 0;
   17869                 :            : }
   17870                 :            : 
   17871                 :            : /**
   17872                 :            :  * Query a DV flow rule for its statistics via DevX.
   17873                 :            :  *
   17874                 :            :  * @param[in] dev
   17875                 :            :  *   Pointer to Ethernet device.
   17876                 :            :  * @param[in] cnt_idx
   17877                 :            :  *   Index to the flow counter.
   17878                 :            :  * @param[out] data
   17879                 :            :  *   Data retrieved by the query.
   17880                 :            :  * @param[out] error
   17881                 :            :  *   Perform verbose error reporting if not NULL.
   17882                 :            :  *
   17883                 :            :  * @return
   17884                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   17885                 :            :  */
   17886                 :            : static int
   17887                 :          0 : flow_dv_query_count(struct rte_eth_dev *dev, uint32_t cnt_idx, void *data,
   17888                 :            :                     struct rte_flow_error *error)
   17889                 :            : {
   17890                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17891                 :            :         struct rte_flow_query_count *qc = data;
   17892                 :            : 
   17893         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
   17894                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17895                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17896                 :            :                                           NULL,
   17897                 :            :                                           "counters are not supported");
   17898         [ #  # ]:          0 :         if (cnt_idx) {
   17899                 :            :                 uint64_t pkts, bytes;
   17900                 :            :                 struct mlx5_flow_counter *cnt;
   17901                 :          0 :                 int err = _flow_dv_query_count(dev, cnt_idx, &pkts, &bytes);
   17902                 :            : 
   17903         [ #  # ]:          0 :                 if (err)
   17904                 :          0 :                         return rte_flow_error_set(error, -err,
   17905                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17906                 :            :                                         NULL, "cannot read counters");
   17907                 :            :                 cnt = flow_dv_counter_get_by_idx(dev, cnt_idx, NULL);
   17908                 :          0 :                 qc->hits_set = 1;
   17909                 :          0 :                 qc->bytes_set = 1;
   17910                 :          0 :                 qc->hits = pkts - cnt->hits;
   17911                 :          0 :                 qc->bytes = bytes - cnt->bytes;
   17912         [ #  # ]:          0 :                 if (qc->reset) {
   17913                 :          0 :                         cnt->hits = pkts;
   17914                 :          0 :                         cnt->bytes = bytes;
   17915                 :            :                 }
   17916                 :          0 :                 return 0;
   17917                 :            :         }
   17918                 :          0 :         return rte_flow_error_set(error, EINVAL,
   17919                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17920                 :            :                                   NULL,
   17921                 :            :                                   "counters are not available");
   17922                 :            : }
   17923                 :            : 
   17924                 :            : int
   17925                 :          0 : flow_dv_action_query(struct rte_eth_dev *dev,
   17926                 :            :                      const struct rte_flow_action_handle *handle, void *data,
   17927                 :            :                      struct rte_flow_error *error)
   17928                 :            : {
   17929                 :            :         struct mlx5_age_param *age_param;
   17930                 :            :         struct rte_flow_query_age *resp;
   17931                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   17932                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   17933                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   17934                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17935                 :            :         struct mlx5_aso_ct_action *ct;
   17936                 :            :         uint16_t owner;
   17937                 :            :         uint32_t dev_idx;
   17938                 :            : 
   17939   [ #  #  #  # ]:          0 :         switch (type) {
   17940                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   17941                 :          0 :                 age_param = &flow_aso_age_get_by_idx(dev, idx)->age_params;
   17942                 :            :                 resp = data;
   17943                 :          0 :                 resp->aged = rte_atomic_load_explicit(&age_param->state,
   17944                 :            :                                               rte_memory_order_relaxed) == AGE_TMOUT ?
   17945                 :          0 :                                                                           1 : 0;
   17946                 :          0 :                 resp->sec_since_last_hit_valid = !resp->aged;
   17947         [ #  # ]:          0 :                 if (resp->sec_since_last_hit_valid)
   17948                 :          0 :                         resp->sec_since_last_hit = rte_atomic_load_explicit
   17949                 :            :                              (&age_param->sec_since_last_hit, rte_memory_order_relaxed);
   17950                 :            :                 return 0;
   17951                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   17952                 :          0 :                 return flow_dv_query_count(dev, idx, data, error);
   17953                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   17954                 :          0 :                 owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(idx);
   17955         [ #  # ]:          0 :                 if (owner != PORT_ID(priv))
   17956                 :          0 :                         return rte_flow_error_set(error, EACCES,
   17957                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17958                 :            :                                         NULL,
   17959                 :            :                                         "CT object owned by another port");
   17960                 :          0 :                 dev_idx = MLX5_INDIRECT_ACT_CT_GET_IDX(idx);
   17961                 :          0 :                 ct = flow_aso_ct_get_by_dev_idx(dev, dev_idx);
   17962                 :            :                 MLX5_ASSERT(ct);
   17963         [ #  # ]:          0 :                 if (!ct->refcnt)
   17964                 :          0 :                         return rte_flow_error_set(error, EFAULT,
   17965                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17966                 :            :                                         NULL,
   17967                 :            :                                         "CT object is inactive");
   17968                 :          0 :                 ((struct rte_flow_action_conntrack *)data)->peer_port =
   17969                 :          0 :                                                         ct->peer;
   17970                 :          0 :                 ((struct rte_flow_action_conntrack *)data)->is_original_dir =
   17971                 :          0 :                                                         ct->is_original;
   17972         [ #  # ]:          0 :                 if (mlx5_aso_ct_query_by_wqe(priv->sh, MLX5_HW_INV_QUEUE, ct,
   17973                 :            :                                         data, NULL, true))
   17974                 :          0 :                         return rte_flow_error_set(error, EIO,
   17975                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17976                 :            :                                         NULL,
   17977                 :            :                                         "Failed to query CT context");
   17978                 :            :                 return 0;
   17979                 :          0 :         default:
   17980                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17981                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17982                 :            :                                           "action type query not supported");
   17983                 :            :         }
   17984                 :            : }
   17985                 :            : 
   17986                 :            : /**
   17987                 :            :  * Query a flow rule AGE action for aging information.
   17988                 :            :  *
   17989                 :            :  * @param[in] dev
   17990                 :            :  *   Pointer to Ethernet device.
   17991                 :            :  * @param[in] flow
   17992                 :            :  *   Pointer to the sub flow.
   17993                 :            :  * @param[out] data
   17994                 :            :  *   data retrieved by the query.
   17995                 :            :  * @param[out] error
   17996                 :            :  *   Perform verbose error reporting if not NULL.
   17997                 :            :  *
   17998                 :            :  * @return
   17999                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   18000                 :            :  */
   18001                 :            : static int
   18002                 :          0 : flow_dv_query_age(struct rte_eth_dev *dev, struct rte_flow *flow,
   18003                 :            :                   void *data, struct rte_flow_error *error)
   18004                 :            : {
   18005                 :            :         struct rte_flow_query_age *resp = data;
   18006                 :            :         struct mlx5_age_param *age_param;
   18007                 :            : 
   18008         [ #  # ]:          0 :         if (flow->age) {
   18009                 :            :                 struct mlx5_aso_age_action *act =
   18010                 :          0 :                                      flow_aso_age_get_by_idx(dev, flow->age);
   18011                 :            : 
   18012                 :          0 :                 age_param = &act->age_params;
   18013         [ #  # ]:          0 :         } else if (flow->counter) {
   18014                 :            :                 age_param = flow_dv_counter_idx_get_age(dev, flow->counter);
   18015                 :            : 
   18016         [ #  # ]:          0 :                 if (!age_param || !age_param->timeout)
   18017                 :          0 :                         return rte_flow_error_set
   18018                 :            :                                         (error, EINVAL,
   18019                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18020                 :            :                                          NULL, "cannot read age data");
   18021                 :            :         } else {
   18022                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   18023                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18024                 :            :                                           NULL, "age data not available");
   18025                 :            :         }
   18026                 :          0 :         resp->aged = rte_atomic_load_explicit(&age_param->state, rte_memory_order_relaxed) ==
   18027                 :          0 :                                      AGE_TMOUT ? 1 : 0;
   18028                 :          0 :         resp->sec_since_last_hit_valid = !resp->aged;
   18029         [ #  # ]:          0 :         if (resp->sec_since_last_hit_valid)
   18030                 :          0 :                 resp->sec_since_last_hit = rte_atomic_load_explicit
   18031                 :            :                              (&age_param->sec_since_last_hit, rte_memory_order_relaxed);
   18032                 :            :         return 0;
   18033                 :            : }
   18034                 :            : 
   18035                 :            : /**
   18036                 :            :  * Query a flow.
   18037                 :            :  *
   18038                 :            :  * @see rte_flow_query()
   18039                 :            :  * @see rte_flow_ops
   18040                 :            :  */
   18041                 :            : static int
   18042                 :          0 : flow_dv_query(struct rte_eth_dev *dev,
   18043                 :            :               struct rte_flow *flow __rte_unused,
   18044                 :            :               const struct rte_flow_action *actions __rte_unused,
   18045                 :            :               void *data __rte_unused,
   18046                 :            :               struct rte_flow_error *error __rte_unused)
   18047                 :            : {
   18048                 :            :         int ret = -EINVAL;
   18049                 :            : 
   18050         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
   18051   [ #  #  #  # ]:          0 :                 switch (actions->type) {
   18052                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   18053                 :            :                         break;
   18054                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   18055                 :          0 :                         ret = flow_dv_query_count(dev, flow->counter, data,
   18056                 :            :                                                   error);
   18057                 :          0 :                         break;
   18058                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   18059                 :          0 :                         ret = flow_dv_query_age(dev, flow, data, error);
   18060                 :          0 :                         break;
   18061                 :          0 :                 default:
   18062                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   18063                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   18064                 :            :                                                   actions,
   18065                 :            :                                                   "action not supported");
   18066                 :            :                 }
   18067                 :            :         }
   18068                 :            :         return ret;
   18069                 :            : }
   18070                 :            : 
   18071                 :            : /**
   18072                 :            :  * Destroy the meter table set.
   18073                 :            :  * Lock free, (mutex should be acquired by caller).
   18074                 :            :  *
   18075                 :            :  * @param[in] dev
   18076                 :            :  *   Pointer to Ethernet device.
   18077                 :            :  * @param[in] fm
   18078                 :            :  *   Meter information table.
   18079                 :            :  */
   18080                 :            : static void
   18081                 :          0 : flow_dv_destroy_mtr_tbls(struct rte_eth_dev *dev,
   18082                 :            :                         struct mlx5_flow_meter_info *fm)
   18083                 :            : {
   18084                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18085                 :            :         int i;
   18086                 :            : 
   18087   [ #  #  #  # ]:          0 :         if (!fm || !priv->sh->config.dv_flow_en)
   18088                 :            :                 return;
   18089         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18090         [ #  # ]:          0 :                 if (fm->drop_rule[i]) {
   18091                 :            :                         claim_zero(mlx5_flow_os_destroy_flow(fm->drop_rule[i]));
   18092                 :          0 :                         fm->drop_rule[i] = NULL;
   18093                 :            :                 }
   18094                 :            :         }
   18095                 :            : }
   18096                 :            : 
   18097                 :            : static void
   18098                 :          0 : flow_dv_destroy_mtr_drop_tbls(struct rte_eth_dev *dev)
   18099                 :            : {
   18100                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18101                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18102                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   18103                 :            :         int i, j;
   18104                 :            : 
   18105         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18106         [ #  # ]:          0 :                 if (mtrmng->def_rule[i]) {
   18107                 :            :                         claim_zero(mlx5_flow_os_destroy_flow
   18108                 :            :                                         (mtrmng->def_rule[i]));
   18109                 :          0 :                         mtrmng->def_rule[i] = NULL;
   18110                 :            :                 }
   18111         [ #  # ]:          0 :                 if (mtrmng->def_matcher[i]) {
   18112                 :          0 :                         tbl = container_of(mtrmng->def_matcher[i]->tbl,
   18113                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   18114                 :          0 :                         mlx5_list_unregister(tbl->matchers,
   18115                 :            :                                              &mtrmng->def_matcher[i]->entry);
   18116                 :          0 :                         mtrmng->def_matcher[i] = NULL;
   18117                 :            :                 }
   18118         [ #  # ]:          0 :                 for (j = 0; j < MLX5_REG_BITS; j++) {
   18119         [ #  # ]:          0 :                         if (mtrmng->drop_matcher[i][j]) {
   18120                 :            :                                 tbl =
   18121                 :          0 :                                 container_of(mtrmng->drop_matcher[i][j]->tbl,
   18122                 :            :                                              struct mlx5_flow_tbl_data_entry,
   18123                 :            :                                              tbl);
   18124                 :          0 :                                 mlx5_list_unregister(tbl->matchers,
   18125                 :            :                                             &mtrmng->drop_matcher[i][j]->entry);
   18126                 :          0 :                                 mtrmng->drop_matcher[i][j] = NULL;
   18127                 :            :                         }
   18128                 :            :                 }
   18129         [ #  # ]:          0 :                 if (mtrmng->drop_tbl[i]) {
   18130                 :          0 :                         flow_dv_tbl_resource_release(MLX5_SH(dev),
   18131                 :            :                                 mtrmng->drop_tbl[i]);
   18132                 :          0 :                         mtrmng->drop_tbl[i] = NULL;
   18133                 :            :                 }
   18134                 :            :         }
   18135                 :          0 : }
   18136                 :            : 
   18137                 :            : /* Number of meter flow actions, count and jump or count and drop. */
   18138                 :            : #define METER_ACTIONS 2
   18139                 :            : 
   18140                 :            : static void
   18141                 :          0 : __flow_dv_destroy_domain_def_policy(struct rte_eth_dev *dev,
   18142                 :            :                                     enum mlx5_meter_domain domain)
   18143                 :            : {
   18144                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18145                 :          0 :         struct mlx5_flow_meter_def_policy *def_policy =
   18146                 :          0 :                         priv->sh->mtrmng->def_policy[domain];
   18147                 :            : 
   18148                 :          0 :         __flow_dv_destroy_sub_policy_rules(dev, &def_policy->sub_policy);
   18149                 :          0 :         mlx5_free(def_policy);
   18150                 :          0 :         priv->sh->mtrmng->def_policy[domain] = NULL;
   18151                 :          0 : }
   18152                 :            : 
   18153                 :            : /**
   18154                 :            :  * Destroy the default policy table set.
   18155                 :            :  *
   18156                 :            :  * @param[in] dev
   18157                 :            :  *   Pointer to Ethernet device.
   18158                 :            :  */
   18159                 :            : static void
   18160                 :          0 : flow_dv_destroy_def_policy(struct rte_eth_dev *dev)
   18161                 :            : {
   18162                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18163                 :            :         int i;
   18164                 :            : 
   18165         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++)
   18166         [ #  # ]:          0 :                 if (priv->sh->mtrmng->def_policy[i])
   18167                 :          0 :                         __flow_dv_destroy_domain_def_policy(dev,
   18168                 :            :                                         (enum mlx5_meter_domain)i);
   18169                 :          0 :         priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
   18170                 :          0 : }
   18171                 :            : 
   18172                 :            : static int
   18173                 :          0 : __flow_dv_create_policy_flow(struct rte_eth_dev *dev,
   18174                 :            :                         uint32_t color_reg_c_idx,
   18175                 :            :                         enum rte_color color, struct mlx5_flow_dv_matcher *matcher,
   18176                 :            :                         int actions_n, void *actions,
   18177                 :            :                         bool match_src_port, const struct rte_flow_item *item,
   18178                 :            :                         void **rule, const struct rte_flow_attr *attr)
   18179                 :            : {
   18180                 :            :         int ret;
   18181                 :          0 :         struct mlx5_flow_dv_match_params value = {
   18182                 :            :                 .size = sizeof(value.buf),
   18183                 :            :         };
   18184                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18185                 :            :         uint8_t misc_mask;
   18186                 :            : 
   18187   [ #  #  #  # ]:          0 :         if (match_src_port && priv->sh->esw_mode) {
   18188   [ #  #  #  # ]:          0 :                 if (item && item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT)
   18189                 :          0 :                         ret = flow_dv_translate_item_represented_port(dev, value.buf,
   18190                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_V);
   18191   [ #  #  #  # ]:          0 :                 else if (item && item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
   18192                 :          0 :                         ret = flow_dv_translate_item_port_representor(dev, value.buf,
   18193                 :            :                                                                       MLX5_SET_MATCHER_SW_V);
   18194                 :            :                 else
   18195                 :          0 :                         ret = flow_dv_translate_item_port_id(dev, value.buf,
   18196                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_V);
   18197         [ #  # ]:          0 :                 if (ret) {
   18198                 :          0 :                         DRV_LOG(ERR, "Failed to create meter policy%d flow's"
   18199                 :            :                                 " value with port.", color);
   18200                 :          0 :                         return -1;
   18201                 :            :                 }
   18202                 :            :         }
   18203                 :          0 :         flow_dv_match_meta_reg(value.buf, (enum modify_reg)color_reg_c_idx,
   18204                 :            :                                rte_col_2_mlx5_col(color), UINT32_MAX);
   18205         [ #  # ]:          0 :         misc_mask = flow_dv_matcher_enable(matcher->mask.buf);
   18206                 :            :         __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18207                 :          0 :         ret = mlx5_flow_os_create_flow(matcher->matcher_object, (void *)&value,
   18208                 :            :                                        actions_n, actions, rule);
   18209                 :            :         if (ret) {
   18210                 :          0 :                 DRV_LOG(ERR, "Failed to create meter policy%d flow.", color);
   18211                 :          0 :                 return -1;
   18212                 :            :         }
   18213                 :            :         return 0;
   18214                 :            : }
   18215                 :            : 
   18216                 :            : static int
   18217                 :          0 : __flow_dv_create_policy_matcher(struct rte_eth_dev *dev,
   18218                 :            :                         uint32_t color_reg_c_idx,
   18219                 :            :                         uint16_t priority,
   18220                 :            :                         struct mlx5_flow_meter_sub_policy *sub_policy,
   18221                 :            :                         const struct rte_flow_attr *attr,
   18222                 :            :                         bool match_src_port,
   18223                 :            :                         const struct rte_flow_item *item,
   18224                 :            :                         struct mlx5_flow_dv_matcher **policy_matcher,
   18225                 :            :                         struct rte_flow_error *error)
   18226                 :            : {
   18227                 :            :         struct mlx5_list_entry *entry;
   18228                 :          0 :         struct mlx5_flow_tbl_resource *tbl_rsc = sub_policy->tbl_rsc;
   18229                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   18230                 :            :                 .mask = {
   18231                 :            :                         .size = sizeof(matcher.mask.buf),
   18232                 :            :                 },
   18233                 :            :                 .tbl = tbl_rsc,
   18234                 :            :         };
   18235                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   18236                 :            :                 .error = error,
   18237                 :            :                 .data = &matcher,
   18238                 :            :         };
   18239                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18240                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18241                 :            :         const uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
   18242                 :            :         int ret;
   18243                 :            : 
   18244   [ #  #  #  # ]:          0 :         if (match_src_port && priv->sh->esw_mode) {
   18245   [ #  #  #  # ]:          0 :                 if (item && item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT)
   18246                 :          0 :                         ret = flow_dv_translate_item_represented_port(dev, matcher.mask.buf,
   18247                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_M);
   18248   [ #  #  #  # ]:          0 :                 else if (item && item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
   18249                 :          0 :                         ret = flow_dv_translate_item_port_representor(dev, matcher.mask.buf,
   18250                 :            :                                                                       MLX5_SET_MATCHER_SW_M);
   18251                 :            :                 else
   18252                 :          0 :                         ret = flow_dv_translate_item_port_id(dev, matcher.mask.buf,
   18253                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_M);
   18254         [ #  # ]:          0 :                 if (ret) {
   18255                 :          0 :                         DRV_LOG(ERR, "Failed to register meter policy%d matcher"
   18256                 :            :                                 " with port.", priority);
   18257                 :          0 :                         return -1;
   18258                 :            :                 }
   18259                 :            :         }
   18260                 :          0 :         tbl_data = container_of(tbl_rsc, struct mlx5_flow_tbl_data_entry, tbl);
   18261                 :          0 :         flow_dv_match_meta_reg(matcher.mask.buf,
   18262                 :            :                 (enum modify_reg)color_reg_c_idx, color_mask, color_mask);
   18263                 :          0 :         matcher.priority = priority;
   18264                 :          0 :         matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
   18265                 :            :                                     matcher.mask.size);
   18266                 :          0 :         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18267         [ #  # ]:          0 :         if (!entry) {
   18268                 :          0 :                 DRV_LOG(ERR, "Failed to register meter drop matcher.");
   18269                 :          0 :                 return -1;
   18270                 :            :         }
   18271                 :          0 :         *policy_matcher =
   18272                 :            :                 container_of(entry, struct mlx5_flow_dv_matcher, entry);
   18273                 :          0 :         return 0;
   18274                 :            : }
   18275                 :            : 
   18276                 :            : /**
   18277                 :            :  * Create the policy rules per domain.
   18278                 :            :  *
   18279                 :            :  * @param[in] dev
   18280                 :            :  *   Pointer to Ethernet device.
   18281                 :            :  * @param[in] sub_policy
   18282                 :            :  *    Pointer to sub policy table..
   18283                 :            :  * @param[in] egress
   18284                 :            :  *   Direction of the table.
   18285                 :            :  * @param[in] transfer
   18286                 :            :  *   E-Switch or NIC flow.
   18287                 :            :  * @param[in] acts
   18288                 :            :  *   Pointer to policy action list per color.
   18289                 :            :  *
   18290                 :            :  * @return
   18291                 :            :  *   0 on success, -1 otherwise.
   18292                 :            :  */
   18293                 :            : static int
   18294                 :          0 : __flow_dv_create_domain_policy_rules(struct rte_eth_dev *dev,
   18295                 :            :                 struct mlx5_flow_meter_sub_policy *sub_policy,
   18296                 :            :                 uint8_t egress, uint8_t transfer, bool *match_src_port,
   18297                 :            :                 struct mlx5_meter_policy_acts acts[RTE_COLORS])
   18298                 :            : {
   18299                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18300                 :            :         struct rte_flow_error flow_err;
   18301                 :            :         uint32_t color_reg_c_idx;
   18302                 :          0 :         struct rte_flow_attr attr = {
   18303                 :            :                 .group = MLX5_FLOW_TABLE_LEVEL_POLICY,
   18304                 :            :                 .priority = 0,
   18305                 :            :                 .ingress = 0,
   18306                 :          0 :                 .egress = !!egress,
   18307                 :          0 :                 .transfer = !!transfer,
   18308                 :            :                 .reserved = 0,
   18309                 :            :         };
   18310                 :            :         int i;
   18311                 :            :         uint16_t priority;
   18312                 :          0 :         int ret = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &flow_err);
   18313                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   18314                 :          0 :         struct mlx5_sub_policy_color_rule *tmp_rules[RTE_COLORS] = {NULL};
   18315                 :            : 
   18316         [ #  # ]:          0 :         if (ret < 0)
   18317                 :            :                 return -1;
   18318                 :            :         /* Create policy table with POLICY level. */
   18319         [ #  # ]:          0 :         if (!sub_policy->tbl_rsc)
   18320                 :          0 :                 sub_policy->tbl_rsc = flow_dv_tbl_resource_get(dev,
   18321                 :            :                                 MLX5_FLOW_TABLE_LEVEL_POLICY,
   18322                 :            :                                 egress, transfer, false, NULL, 0, 0,
   18323                 :          0 :                                 sub_policy->idx, &flow_err);
   18324         [ #  # ]:          0 :         if (!sub_policy->tbl_rsc) {
   18325                 :          0 :                 DRV_LOG(ERR,
   18326                 :            :                         "Failed to create meter sub policy table.");
   18327                 :          0 :                 return -1;
   18328                 :            :         }
   18329                 :            :         /* Prepare matchers. */
   18330                 :          0 :         color_reg_c_idx = ret;
   18331         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   18332                 :          0 :                 TAILQ_INIT(&sub_policy->color_rules[i]);
   18333         [ #  # ]:          0 :                 if (!acts[i].actions_n)
   18334                 :          0 :                         continue;
   18335                 :          0 :                 color_rule = mlx5_malloc(MLX5_MEM_ZERO,
   18336                 :            :                                 sizeof(struct mlx5_sub_policy_color_rule),
   18337                 :            :                                 0, SOCKET_ID_ANY);
   18338         [ #  # ]:          0 :                 if (!color_rule) {
   18339                 :          0 :                         DRV_LOG(ERR, "No memory to create color rule.");
   18340                 :          0 :                         goto err_exit;
   18341                 :            :                 }
   18342                 :          0 :                 tmp_rules[i] = color_rule;
   18343                 :          0 :                 TAILQ_INSERT_TAIL(&sub_policy->color_rules[i],
   18344                 :            :                                   color_rule, next_port);
   18345                 :          0 :                 color_rule->src_port = priv->representor_id;
   18346                 :          0 :                 priority = (match_src_port[i] == match_src_port[RTE_COLOR_GREEN]) ?
   18347                 :          0 :                            MLX5_MTR_POLICY_MATCHER_PRIO : (MLX5_MTR_POLICY_MATCHER_PRIO + 1);
   18348                 :            :                 /* Create matchers for colors. */
   18349         [ #  # ]:          0 :                 if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
   18350                 :            :                                 priority, sub_policy,
   18351                 :            :                                 &attr, match_src_port[i], NULL,
   18352                 :            :                                 &color_rule->matcher, &flow_err)) {
   18353                 :          0 :                         DRV_LOG(ERR, "Failed to create color%u matcher.", i);
   18354                 :          0 :                         goto err_exit;
   18355                 :            :                 }
   18356                 :            :                 /* Create flow, matching color. */
   18357         [ #  # ]:          0 :                 if (__flow_dv_create_policy_flow(dev,
   18358                 :            :                                 color_reg_c_idx, (enum rte_color)i,
   18359                 :            :                                 color_rule->matcher,
   18360                 :          0 :                                 acts[i].actions_n, acts[i].dv_actions,
   18361                 :          0 :                                 match_src_port[i], NULL, &color_rule->rule,
   18362                 :            :                                 &attr)) {
   18363                 :          0 :                         DRV_LOG(ERR, "Failed to create color%u rule.", i);
   18364                 :          0 :                         goto err_exit;
   18365                 :            :                 }
   18366                 :            :         }
   18367                 :            :         return 0;
   18368                 :            : err_exit:
   18369                 :            :         /* All the policy rules will be cleared. */
   18370                 :            :         do {
   18371                 :          0 :                 color_rule = tmp_rules[i];
   18372         [ #  # ]:          0 :                 if (color_rule) {
   18373         [ #  # ]:          0 :                         if (color_rule->rule)
   18374                 :            :                                 mlx5_flow_os_destroy_flow(color_rule->rule);
   18375         [ #  # ]:          0 :                         if (color_rule->matcher) {
   18376                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl =
   18377                 :          0 :                                         container_of(color_rule->matcher->tbl,
   18378                 :            :                                                      typeof(*tbl), tbl);
   18379                 :          0 :                                 mlx5_list_unregister(tbl->matchers,
   18380                 :            :                                                 &color_rule->matcher->entry);
   18381                 :            :                         }
   18382         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[i],
   18383                 :            :                                      color_rule, next_port);
   18384                 :          0 :                         mlx5_free(color_rule);
   18385                 :            :                 }
   18386         [ #  # ]:          0 :         } while (i--);
   18387                 :            :         return -1;
   18388                 :            : }
   18389                 :            : 
   18390                 :            : static int
   18391                 :          0 : __flow_dv_create_policy_acts_rules(struct rte_eth_dev *dev,
   18392                 :            :                         struct mlx5_flow_meter_policy *mtr_policy,
   18393                 :            :                         struct mlx5_flow_meter_sub_policy *sub_policy,
   18394                 :            :                         uint32_t domain)
   18395                 :            : {
   18396                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18397                 :            :         struct mlx5_meter_policy_acts acts[RTE_COLORS];
   18398                 :            :         struct mlx5_flow_dv_tag_resource *tag;
   18399                 :            :         struct mlx5_flow_dv_port_id_action_resource *port_action;
   18400                 :            :         struct mlx5_hrxq *hrxq;
   18401                 :          0 :         struct mlx5_flow_meter_info *next_fm[RTE_COLORS] = {NULL};
   18402                 :            :         struct mlx5_flow_meter_policy *next_policy;
   18403                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy;
   18404                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18405                 :            :         struct rte_flow_error error;
   18406                 :          0 :         uint8_t egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18407                 :          0 :         uint8_t transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18408   [ #  #  #  #  :          0 :         bool mtr_first = egress || (transfer && priv->representor_id != UINT16_MAX);
                   #  # ]
   18409                 :          0 :         bool match_src_port[RTE_COLORS] = {false};
   18410                 :            :         int i;
   18411                 :            : 
   18412                 :            :         /* If RSS or Queue, no previous actions / rules is created. */
   18413         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   18414                 :          0 :                 acts[i].actions_n = 0;
   18415         [ #  # ]:          0 :                 if (i == RTE_COLOR_RED) {
   18416                 :            :                         /* Only support drop on red. */
   18417                 :          0 :                         acts[i].dv_actions[0] =
   18418                 :          0 :                                 mtr_policy->dr_drop_action[domain];
   18419                 :          0 :                         acts[i].actions_n = 1;
   18420                 :          0 :                         continue;
   18421                 :            :                 }
   18422         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR) {
   18423                 :          0 :                         struct rte_flow_attr attr = {
   18424                 :            :                                 .transfer = transfer
   18425                 :            :                         };
   18426                 :            : 
   18427                 :          0 :                         next_fm[i] = mlx5_flow_meter_find(priv,
   18428                 :            :                                         mtr_policy->act_cnt[i].next_mtr_id,
   18429                 :            :                                         NULL);
   18430         [ #  # ]:          0 :                         if (!next_fm[i]) {
   18431                 :          0 :                                 DRV_LOG(ERR,
   18432                 :            :                                         "Failed to get next hierarchy meter.");
   18433                 :          0 :                                 goto err_exit;
   18434                 :            :                         }
   18435         [ #  # ]:          0 :                         if (mlx5_flow_meter_attach(priv, next_fm[i],
   18436                 :            :                                                    &attr, &error)) {
   18437                 :          0 :                                 DRV_LOG(ERR, "%s", error.message);
   18438                 :          0 :                                 next_fm[i] = NULL;
   18439                 :          0 :                                 goto err_exit;
   18440                 :            :                         }
   18441                 :            :                         /* Meter action must be the first for TX. */
   18442         [ #  # ]:          0 :                         if (mtr_first) {
   18443                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18444         [ #  # ]:          0 :                                         (next_fm[i]->color_aware && i == RTE_COLOR_YELLOW) ?
   18445         [ #  # ]:          0 :                                                 next_fm[i]->meter_action_y :
   18446                 :            :                                                 next_fm[i]->meter_action_g;
   18447                 :          0 :                                 acts[i].actions_n++;
   18448                 :            :                         }
   18449                 :            :                 }
   18450         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].rix_mark) {
   18451                 :          0 :                         tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG],
   18452                 :            :                                         mtr_policy->act_cnt[i].rix_mark);
   18453         [ #  # ]:          0 :                         if (!tag) {
   18454                 :          0 :                                 DRV_LOG(ERR, "Failed to find "
   18455                 :            :                                 "mark action for policy.");
   18456                 :          0 :                                 goto err_exit;
   18457                 :            :                         }
   18458                 :          0 :                         acts[i].dv_actions[acts[i].actions_n] = tag->action;
   18459                 :          0 :                         acts[i].actions_n++;
   18460                 :            :                 }
   18461         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].modify_hdr) {
   18462                 :          0 :                         acts[i].dv_actions[acts[i].actions_n] =
   18463                 :          0 :                                 mtr_policy->act_cnt[i].modify_hdr->action;
   18464                 :          0 :                         acts[i].actions_n++;
   18465                 :            :                 }
   18466         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action) {
   18467   [ #  #  #  #  :          0 :                         switch (mtr_policy->act_cnt[i].fate_action) {
                      # ]
   18468                 :          0 :                         case MLX5_FLOW_FATE_PORT_ID:
   18469                 :          0 :                                 port_action = mlx5_ipool_get
   18470                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_PORT_ID],
   18471                 :            :                                 mtr_policy->act_cnt[i].rix_port_id_action);
   18472         [ #  # ]:          0 :                                 if (!port_action) {
   18473                 :          0 :                                         DRV_LOG(ERR, "Failed to find "
   18474                 :            :                                                 "port action for policy.");
   18475                 :          0 :                                         goto err_exit;
   18476                 :            :                                 }
   18477                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18478                 :          0 :                                         port_action->action;
   18479                 :          0 :                                 acts[i].actions_n++;
   18480                 :          0 :                                 match_src_port[i] = true;
   18481                 :          0 :                                 break;
   18482                 :          0 :                         case MLX5_FLOW_FATE_DROP:
   18483                 :            :                         case MLX5_FLOW_FATE_JUMP:
   18484                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18485                 :          0 :                                 mtr_policy->act_cnt[i].dr_jump_action[domain];
   18486                 :          0 :                                 acts[i].actions_n++;
   18487                 :          0 :                                 break;
   18488                 :          0 :                         case MLX5_FLOW_FATE_SHARED_RSS:
   18489                 :            :                         case MLX5_FLOW_FATE_QUEUE:
   18490                 :          0 :                                 hrxq = mlx5_ipool_get
   18491                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_HRXQ],
   18492                 :            :                                          sub_policy->rix_hrxq[i]);
   18493         [ #  # ]:          0 :                                 if (!hrxq) {
   18494                 :          0 :                                         DRV_LOG(ERR, "Failed to find "
   18495                 :            :                                                 "queue action for policy.");
   18496                 :          0 :                                         goto err_exit;
   18497                 :            :                                 }
   18498                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18499                 :          0 :                                         hrxq->action;
   18500                 :          0 :                                 acts[i].actions_n++;
   18501                 :          0 :                                 break;
   18502                 :          0 :                         case MLX5_FLOW_FATE_MTR:
   18503         [ #  # ]:          0 :                                 if (!next_fm[i]) {
   18504                 :          0 :                                         DRV_LOG(ERR,
   18505                 :            :                                                 "No next hierarchy meter.");
   18506                 :          0 :                                         goto err_exit;
   18507                 :            :                                 }
   18508         [ #  # ]:          0 :                                 if (!mtr_first) {
   18509                 :          0 :                                         acts[i].dv_actions[acts[i].actions_n] =
   18510         [ #  # ]:          0 :                                                 (next_fm[i]->color_aware && i == RTE_COLOR_YELLOW) ?
   18511         [ #  # ]:          0 :                                                         next_fm[i]->meter_action_y :
   18512                 :            :                                                         next_fm[i]->meter_action_g;
   18513                 :          0 :                                         acts[i].actions_n++;
   18514                 :            :                                 }
   18515         [ #  # ]:          0 :                                 if (mtr_policy->act_cnt[i].next_sub_policy) {
   18516                 :            :                                         next_sub_policy =
   18517                 :            :                                         mtr_policy->act_cnt[i].next_sub_policy;
   18518                 :            :                                 } else {
   18519                 :            :                                         next_policy =
   18520                 :          0 :                                                 mlx5_flow_meter_policy_find(dev,
   18521                 :            :                                                                 next_fm[i]->policy_id, NULL);
   18522                 :            :                                         MLX5_ASSERT(next_policy);
   18523                 :          0 :                                         next_sub_policy =
   18524                 :          0 :                                         next_policy->sub_policys[domain][0];
   18525                 :            :                                 }
   18526                 :            :                                 tbl_data =
   18527                 :          0 :                                         container_of(next_sub_policy->tbl_rsc,
   18528                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18529                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n++] =
   18530                 :          0 :                                                         tbl_data->jump.action;
   18531         [ #  # ]:          0 :                                 if (mtr_policy->act_cnt[i].modify_hdr)
   18532                 :          0 :                                         match_src_port[i] = !!transfer;
   18533                 :            :                                 break;
   18534                 :            :                         default:
   18535                 :            :                                 /*Queue action do nothing*/
   18536                 :            :                                 break;
   18537                 :            :                         }
   18538                 :            :                 }
   18539                 :            :         }
   18540         [ #  # ]:          0 :         if (__flow_dv_create_domain_policy_rules(dev, sub_policy,
   18541                 :            :                                 egress, transfer, match_src_port, acts)) {
   18542                 :          0 :                 DRV_LOG(ERR,
   18543                 :            :                         "Failed to create policy rules per domain.");
   18544                 :          0 :                 goto err_exit;
   18545                 :            :         }
   18546   [ #  #  #  # ]:          0 :         if (match_src_port[RTE_COLOR_GREEN] || match_src_port[RTE_COLOR_YELLOW]) {
   18547                 :          0 :                 mtr_policy->match_port = 1;
   18548                 :          0 :                 mtr_policy->hierarchy_match_port = 1;
   18549                 :            :         }
   18550                 :            :         return 0;
   18551                 :            : err_exit:
   18552         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++)
   18553         [ #  # ]:          0 :                 if (next_fm[i])
   18554                 :          0 :                         mlx5_flow_meter_detach(priv, next_fm[i]);
   18555                 :            :         return -1;
   18556                 :            : }
   18557                 :            : 
   18558                 :            : /**
   18559                 :            :  * Create the policy rules.
   18560                 :            :  *
   18561                 :            :  * @param[in] dev
   18562                 :            :  *   Pointer to Ethernet device.
   18563                 :            :  * @param[in,out] mtr_policy
   18564                 :            :  *   Pointer to meter policy table.
   18565                 :            :  *
   18566                 :            :  * @return
   18567                 :            :  *   0 on success, -1 otherwise.
   18568                 :            :  */
   18569                 :            : static int
   18570                 :          0 : flow_dv_create_policy_rules(struct rte_eth_dev *dev,
   18571                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
   18572                 :            : {
   18573                 :            :         int i;
   18574                 :            :         int ret = 0;
   18575                 :            :         uint16_t sub_policy_num;
   18576                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_push_thread_workspace();
   18577                 :            : 
   18578                 :            :         RTE_SET_USED(wks);
   18579         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18580                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   18581                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   18582                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18583         [ #  # ]:          0 :                 if (!sub_policy_num)
   18584                 :          0 :                         continue;
   18585                 :            :                 /* Prepare actions list and create policy rules. */
   18586         [ #  # ]:          0 :                 if (__flow_dv_create_policy_acts_rules(dev, mtr_policy,
   18587                 :          0 :                         mtr_policy->sub_policys[i][0], i)) {
   18588                 :          0 :                         DRV_LOG(ERR, "Failed to create policy action "
   18589                 :            :                                 "list per domain.");
   18590                 :            :                         ret = -1;
   18591                 :          0 :                         goto exit;
   18592                 :            :                 }
   18593                 :            :         }
   18594                 :          0 : exit:
   18595                 :          0 :         mlx5_flow_pop_thread_workspace();
   18596                 :          0 :         return ret;
   18597                 :            : }
   18598                 :            : 
   18599                 :            : static int
   18600                 :          0 : __flow_dv_create_domain_def_policy(struct rte_eth_dev *dev, uint32_t domain)
   18601                 :            : {
   18602                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18603                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18604                 :            :         struct mlx5_flow_meter_def_policy *def_policy;
   18605                 :            :         struct mlx5_flow_tbl_resource *jump_tbl;
   18606                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18607                 :            :         uint8_t egress, transfer;
   18608                 :            :         struct rte_flow_error error;
   18609                 :            :         struct mlx5_meter_policy_acts acts[RTE_COLORS];
   18610                 :          0 :         bool match_src_port[RTE_COLORS] = {false};
   18611                 :            :         int ret;
   18612                 :            : 
   18613                 :          0 :         egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18614                 :          0 :         transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18615                 :          0 :         def_policy = mtrmng->def_policy[domain];
   18616         [ #  # ]:          0 :         if (!def_policy) {
   18617                 :          0 :                 def_policy = mlx5_malloc(MLX5_MEM_ZERO,
   18618                 :            :                         sizeof(struct mlx5_flow_meter_def_policy),
   18619                 :            :                         RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
   18620         [ #  # ]:          0 :                 if (!def_policy) {
   18621                 :          0 :                         DRV_LOG(ERR, "Failed to alloc default policy table.");
   18622                 :          0 :                         goto def_policy_error;
   18623                 :            :                 }
   18624                 :          0 :                 mtrmng->def_policy[domain] = def_policy;
   18625                 :            :                 /* Create the meter suffix table with SUFFIX level. */
   18626                 :          0 :                 jump_tbl = flow_dv_tbl_resource_get(dev,
   18627                 :            :                                 MLX5_FLOW_TABLE_LEVEL_METER,
   18628                 :            :                                 egress, transfer, false, NULL, 0,
   18629                 :            :                                 0, MLX5_MTR_TABLE_ID_SUFFIX, &error);
   18630         [ #  # ]:          0 :                 if (!jump_tbl) {
   18631                 :          0 :                         DRV_LOG(ERR,
   18632                 :            :                                 "Failed to create meter suffix table.");
   18633                 :          0 :                         goto def_policy_error;
   18634                 :            :                 }
   18635                 :          0 :                 def_policy->sub_policy.jump_tbl[RTE_COLOR_GREEN] = jump_tbl;
   18636                 :          0 :                 tbl_data = container_of(jump_tbl,
   18637                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18638                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_GREEN] =
   18639                 :          0 :                                                 tbl_data->jump.action;
   18640                 :          0 :                 acts[RTE_COLOR_GREEN].dv_actions[0] = tbl_data->jump.action;
   18641                 :          0 :                 acts[RTE_COLOR_GREEN].actions_n = 1;
   18642                 :            :                 /*
   18643                 :            :                  * YELLOW has the same default policy as GREEN does.
   18644                 :            :                  * G & Y share the same table and action. The 2nd time of table
   18645                 :            :                  * resource getting is just to update the reference count for
   18646                 :            :                  * the releasing stage.
   18647                 :            :                  */
   18648                 :          0 :                 jump_tbl = flow_dv_tbl_resource_get(dev,
   18649                 :            :                                 MLX5_FLOW_TABLE_LEVEL_METER,
   18650                 :            :                                 egress, transfer, false, NULL, 0,
   18651                 :            :                                 0, MLX5_MTR_TABLE_ID_SUFFIX, &error);
   18652         [ #  # ]:          0 :                 if (!jump_tbl) {
   18653                 :          0 :                         DRV_LOG(ERR,
   18654                 :            :                                 "Failed to get meter suffix table.");
   18655                 :          0 :                         goto def_policy_error;
   18656                 :            :                 }
   18657                 :          0 :                 def_policy->sub_policy.jump_tbl[RTE_COLOR_YELLOW] = jump_tbl;
   18658                 :          0 :                 tbl_data = container_of(jump_tbl,
   18659                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18660                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_YELLOW] =
   18661                 :          0 :                                                 tbl_data->jump.action;
   18662                 :          0 :                 acts[RTE_COLOR_YELLOW].dv_actions[0] = tbl_data->jump.action;
   18663                 :          0 :                 acts[RTE_COLOR_YELLOW].actions_n = 1;
   18664                 :            :                 /* Create jump action to the drop table. */
   18665         [ #  # ]:          0 :                 if (!mtrmng->drop_tbl[domain]) {
   18666                 :          0 :                         mtrmng->drop_tbl[domain] = flow_dv_tbl_resource_get
   18667                 :            :                                 (dev, MLX5_FLOW_TABLE_LEVEL_METER,
   18668                 :            :                                  egress, transfer, false, NULL, 0,
   18669                 :            :                                  0, MLX5_MTR_TABLE_ID_DROP, &error);
   18670         [ #  # ]:          0 :                         if (!mtrmng->drop_tbl[domain]) {
   18671                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter "
   18672                 :            :                                         "drop table for default policy.");
   18673                 :          0 :                                 goto def_policy_error;
   18674                 :            :                         }
   18675                 :            :                 }
   18676                 :            :                 /* all RED: unique Drop table for jump action. */
   18677                 :          0 :                 tbl_data = container_of(mtrmng->drop_tbl[domain],
   18678                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18679                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_RED] =
   18680                 :          0 :                                                 tbl_data->jump.action;
   18681                 :          0 :                 acts[RTE_COLOR_RED].dv_actions[0] = tbl_data->jump.action;
   18682                 :          0 :                 acts[RTE_COLOR_RED].actions_n = 1;
   18683                 :            :                 /* Create default policy rules. */
   18684                 :          0 :                 ret = __flow_dv_create_domain_policy_rules(dev,
   18685                 :            :                                         &def_policy->sub_policy,
   18686                 :            :                                         egress, transfer, match_src_port, acts);
   18687         [ #  # ]:          0 :                 if (ret) {
   18688                 :          0 :                         DRV_LOG(ERR, "Failed to create default policy rules.");
   18689                 :          0 :                         goto def_policy_error;
   18690                 :            :                 }
   18691                 :            :         }
   18692                 :            :         return 0;
   18693                 :          0 : def_policy_error:
   18694                 :          0 :         __flow_dv_destroy_domain_def_policy(dev,
   18695                 :            :                                             (enum mlx5_meter_domain)domain);
   18696                 :          0 :         return -1;
   18697                 :            : }
   18698                 :            : 
   18699                 :            : /**
   18700                 :            :  * Create the default policy table set.
   18701                 :            :  *
   18702                 :            :  * @param[in] dev
   18703                 :            :  *   Pointer to Ethernet device.
   18704                 :            :  * @return
   18705                 :            :  *   0 on success, -1 otherwise.
   18706                 :            :  */
   18707                 :            : static int
   18708                 :          0 : flow_dv_create_def_policy(struct rte_eth_dev *dev)
   18709                 :            : {
   18710                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18711                 :            :         int i;
   18712                 :            : 
   18713                 :            :         /* Non-termination policy table. */
   18714         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18715   [ #  #  #  # ]:          0 :                 if (!priv->sh->config.dv_esw_en &&
   18716                 :            :                     i == MLX5_MTR_DOMAIN_TRANSFER)
   18717                 :          0 :                         continue;
   18718         [ #  # ]:          0 :                 if (__flow_dv_create_domain_def_policy(dev, i)) {
   18719                 :          0 :                         DRV_LOG(ERR, "Failed to create default policy");
   18720                 :            :                         /* Rollback the created default policies for others. */
   18721                 :          0 :                         flow_dv_destroy_def_policy(dev);
   18722                 :          0 :                         return -1;
   18723                 :            :                 }
   18724                 :            :         }
   18725                 :            :         return 0;
   18726                 :            : }
   18727                 :            : 
   18728                 :            : /**
   18729                 :            :  * Create the needed meter tables.
   18730                 :            :  * Lock free, (mutex should be acquired by caller).
   18731                 :            :  *
   18732                 :            :  * @param[in] dev
   18733                 :            :  *   Pointer to Ethernet device.
   18734                 :            :  * @param[in] fm
   18735                 :            :  *   Meter information table.
   18736                 :            :  * @param[in] mtr_idx
   18737                 :            :  *   Meter index.
   18738                 :            :  * @param[in] domain_bitmap
   18739                 :            :  *   Domain bitmap.
   18740                 :            :  * @return
   18741                 :            :  *   0 on success, -1 otherwise.
   18742                 :            :  */
   18743                 :            : static int
   18744                 :          0 : flow_dv_create_mtr_tbls(struct rte_eth_dev *dev,
   18745                 :            :                         struct mlx5_flow_meter_info *fm,
   18746                 :            :                         uint32_t mtr_idx,
   18747                 :            :                         uint8_t domain_bitmap)
   18748                 :            : {
   18749                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18750                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18751                 :            :         struct rte_flow_error error;
   18752                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18753                 :            :         uint8_t egress, transfer;
   18754                 :            :         void *actions[METER_ACTIONS];
   18755                 :            :         int domain, ret, i;
   18756                 :            :         struct mlx5_flow_counter *cnt;
   18757                 :          0 :         struct mlx5_flow_dv_match_params value = {
   18758                 :            :                 .size = sizeof(value.buf),
   18759                 :            :         };
   18760                 :          0 :         struct mlx5_flow_dv_match_params matcher_para = {
   18761                 :            :                 .size = sizeof(matcher_para.buf),
   18762                 :            :         };
   18763                 :          0 :         int mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
   18764                 :            :                                                      0, &error);
   18765                 :          0 :         uint32_t mtr_id_mask = (UINT32_C(1) << mtrmng->max_mtr_bits) - 1;
   18766                 :          0 :         uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
   18767                 :            :         struct mlx5_list_entry *entry;
   18768                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   18769                 :            :                 .mask = {
   18770                 :            :                         .size = sizeof(matcher.mask.buf),
   18771                 :            :                 },
   18772                 :            :         };
   18773                 :            :         struct mlx5_flow_dv_matcher *drop_matcher;
   18774                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   18775                 :            :                 .error = &error,
   18776                 :            :                 .data = &matcher,
   18777                 :            :         };
   18778                 :            :         uint8_t misc_mask;
   18779                 :            : 
   18780   [ #  #  #  # ]:          0 :         if (!priv->mtr_en || mtr_id_reg_c < 0) {
   18781                 :          0 :                 rte_errno = ENOTSUP;
   18782                 :          0 :                 return -1;
   18783                 :            :         }
   18784         [ #  # ]:          0 :         for (domain = 0; domain < MLX5_MTR_DOMAIN_MAX; domain++) {
   18785         [ #  # ]:          0 :                 if (!(domain_bitmap & (1 << domain)) ||
   18786   [ #  #  #  # ]:          0 :                         (mtrmng->def_rule[domain] && !fm->drop_cnt))
   18787                 :          0 :                         continue;
   18788                 :          0 :                 egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18789                 :          0 :                 transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18790                 :            :                 /* Create the drop table with METER DROP level. */
   18791         [ #  # ]:          0 :                 if (!mtrmng->drop_tbl[domain]) {
   18792                 :          0 :                         mtrmng->drop_tbl[domain] = flow_dv_tbl_resource_get(dev,
   18793                 :            :                                         MLX5_FLOW_TABLE_LEVEL_METER,
   18794                 :            :                                         egress, transfer, false, NULL, 0,
   18795                 :            :                                         0, MLX5_MTR_TABLE_ID_DROP, &error);
   18796         [ #  # ]:          0 :                         if (!mtrmng->drop_tbl[domain]) {
   18797                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter drop table.");
   18798                 :          0 :                                 goto policy_error;
   18799                 :            :                         }
   18800                 :            :                 }
   18801                 :            :                 /* Create default matcher in drop table. */
   18802                 :          0 :                 matcher.tbl = mtrmng->drop_tbl[domain],
   18803                 :          0 :                 tbl_data = container_of(mtrmng->drop_tbl[domain],
   18804                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   18805         [ #  # ]:          0 :                 if (!mtrmng->def_matcher[domain]) {
   18806                 :          0 :                         flow_dv_match_meta_reg_all(matcher.mask.buf, value.buf,
   18807                 :            :                                        (enum modify_reg)mtr_id_reg_c,
   18808                 :            :                                        0, 0);
   18809                 :          0 :                         matcher.priority = MLX5_MTRS_DEFAULT_RULE_PRIORITY;
   18810                 :          0 :                         matcher.crc = rte_raw_cksum
   18811                 :            :                                         ((const void *)matcher.mask.buf,
   18812                 :            :                                         matcher.mask.size);
   18813                 :          0 :                         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18814         [ #  # ]:          0 :                         if (!entry) {
   18815                 :          0 :                                 DRV_LOG(ERR, "Failed to register meter "
   18816                 :            :                                 "drop default matcher.");
   18817                 :          0 :                                 goto policy_error;
   18818                 :            :                         }
   18819                 :          0 :                         mtrmng->def_matcher[domain] = container_of(entry,
   18820                 :            :                         struct mlx5_flow_dv_matcher, entry);
   18821                 :            :                 }
   18822                 :            :                 /* Create default rule in drop table. */
   18823         [ #  # ]:          0 :                 if (!mtrmng->def_rule[domain]) {
   18824                 :            :                         i = 0;
   18825                 :          0 :                         actions[i++] = priv->sh->dr_drop_action;
   18826                 :          0 :                         flow_dv_match_meta_reg_all(matcher_para.buf, value.buf,
   18827                 :            :                                 (enum modify_reg)mtr_id_reg_c, 0, 0);
   18828         [ #  # ]:          0 :                         misc_mask = flow_dv_matcher_enable(mtrmng->def_matcher[domain]->mask.buf);
   18829                 :            :                         __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18830                 :          0 :                         ret = mlx5_flow_os_create_flow
   18831                 :            :                                 (mtrmng->def_matcher[domain]->matcher_object,
   18832                 :            :                                 (void *)&value, i, actions,
   18833                 :            :                                 &mtrmng->def_rule[domain]);
   18834                 :            :                         if (ret) {
   18835                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter "
   18836                 :            :                                 "default drop rule for drop table.");
   18837                 :          0 :                                 goto policy_error;
   18838                 :            :                         }
   18839                 :            :                 }
   18840         [ #  # ]:          0 :                 if (!fm->drop_cnt)
   18841                 :          0 :                         continue;
   18842                 :            :                 MLX5_ASSERT(mtrmng->max_mtr_bits);
   18843         [ #  # ]:          0 :                 if (!mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1]) {
   18844                 :            :                         /* Create matchers for Drop. */
   18845                 :          0 :                         flow_dv_match_meta_reg_all(matcher.mask.buf, value.buf,
   18846                 :            :                                         (enum modify_reg)mtr_id_reg_c, 0,
   18847                 :            :                                         (mtr_id_mask << mtr_id_offset));
   18848                 :          0 :                         matcher.priority = MLX5_REG_BITS - mtrmng->max_mtr_bits;
   18849                 :          0 :                         matcher.crc = rte_raw_cksum
   18850                 :            :                                         ((const void *)matcher.mask.buf,
   18851                 :            :                                         matcher.mask.size);
   18852                 :          0 :                         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18853         [ #  # ]:          0 :                         if (!entry) {
   18854                 :          0 :                                 DRV_LOG(ERR,
   18855                 :            :                                 "Failed to register meter drop matcher.");
   18856                 :          0 :                                 goto policy_error;
   18857                 :            :                         }
   18858                 :          0 :                         mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1] =
   18859                 :            :                                 container_of(entry, struct mlx5_flow_dv_matcher,
   18860                 :            :                                              entry);
   18861                 :            :                 }
   18862                 :          0 :                 drop_matcher =
   18863                 :          0 :                         mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1];
   18864                 :            :                 /* Create drop rule, matching meter_id only. */
   18865                 :          0 :                 flow_dv_match_meta_reg_all(matcher_para.buf, value.buf,
   18866                 :            :                                 (enum modify_reg)mtr_id_reg_c,
   18867                 :            :                                 (mtr_idx << mtr_id_offset), UINT32_MAX);
   18868                 :            :                 i = 0;
   18869         [ #  # ]:          0 :                 cnt = flow_dv_counter_get_by_idx(dev,
   18870                 :            :                                         fm->drop_cnt, NULL);
   18871                 :          0 :                 actions[i++] = cnt->action;
   18872                 :          0 :                 actions[i++] = priv->sh->dr_drop_action;
   18873         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(drop_matcher->mask.buf);
   18874                 :            :                 __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18875                 :          0 :                 ret = mlx5_flow_os_create_flow(drop_matcher->matcher_object,
   18876                 :            :                                                (void *)&value, i, actions,
   18877                 :            :                                                &fm->drop_rule[domain]);
   18878                 :            :                 if (ret) {
   18879                 :          0 :                         DRV_LOG(ERR, "Failed to create meter "
   18880                 :            :                                 "drop rule for drop table.");
   18881                 :          0 :                                 goto policy_error;
   18882                 :            :                 }
   18883                 :            :         }
   18884                 :            :         return 0;
   18885                 :            : policy_error:
   18886         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18887         [ #  # ]:          0 :                 if (fm->drop_rule[i]) {
   18888                 :            :                         claim_zero(mlx5_flow_os_destroy_flow
   18889                 :            :                                 (fm->drop_rule[i]));
   18890                 :          0 :                         fm->drop_rule[i] = NULL;
   18891                 :            :                 }
   18892                 :            :         }
   18893                 :            :         return -1;
   18894                 :            : }
   18895                 :            : 
   18896                 :            : static struct mlx5_flow_meter_sub_policy *
   18897                 :          0 : __flow_dv_meter_get_rss_sub_policy(struct rte_eth_dev *dev,
   18898                 :            :                 struct mlx5_flow_meter_policy *mtr_policy,
   18899                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS],
   18900                 :            :                 struct mlx5_flow_meter_sub_policy *next_sub_policy,
   18901                 :            :                 bool *is_reuse)
   18902                 :            : {
   18903                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18904                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   18905                 :          0 :         uint32_t sub_policy_idx = 0;
   18906                 :          0 :         uint32_t hrxq_idx[MLX5_MTR_RTE_COLORS] = {0};
   18907                 :            :         uint32_t i, j;
   18908                 :            :         struct mlx5_hrxq *hrxq;
   18909                 :            :         struct mlx5_flow_handle dh;
   18910                 :            :         struct mlx5_meter_policy_action_container *act_cnt;
   18911                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   18912                 :            :         uint16_t sub_policy_num;
   18913                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   18914                 :            : 
   18915                 :            :         MLX5_ASSERT(wks);
   18916                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   18917         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   18918         [ #  # ]:          0 :                 if (!rss_desc[i])
   18919                 :          0 :                         continue;
   18920                 :          0 :                 hrxq = mlx5_hrxq_get(dev, rss_desc[i]);
   18921         [ #  # ]:          0 :                 if (!hrxq) {
   18922                 :            :                         rte_spinlock_unlock(&mtr_policy->sl);
   18923                 :          0 :                         return NULL;
   18924                 :            :                 }
   18925                 :          0 :                 hrxq_idx[i] = hrxq->idx;
   18926                 :            :         }
   18927                 :          0 :         sub_policy_num = (mtr_policy->sub_policy_num >>
   18928                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   18929                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18930         [ #  # ]:          0 :         for (j = 0; j < sub_policy_num; j++) {
   18931         [ #  # ]:          0 :                 for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   18932         [ #  # ]:          0 :                         if (rss_desc[i] &&
   18933                 :          0 :                             hrxq_idx[i] !=
   18934         [ #  # ]:          0 :                             mtr_policy->sub_policys[domain][j]->rix_hrxq[i])
   18935                 :            :                                 break;
   18936                 :            :                 }
   18937         [ #  # ]:          0 :                 if (i >= MLX5_MTR_RTE_COLORS) {
   18938                 :            :                         /*
   18939                 :            :                          * Found the sub policy table with
   18940                 :            :                          * the same queue per color.
   18941                 :            :                          */
   18942                 :            :                         rte_spinlock_unlock(&mtr_policy->sl);
   18943         [ #  # ]:          0 :                         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++)
   18944                 :          0 :                                 mlx5_hrxq_release(dev, hrxq_idx[i]);
   18945                 :          0 :                         *is_reuse = true;
   18946                 :          0 :                         return mtr_policy->sub_policys[domain][j];
   18947                 :            :                 }
   18948                 :            :         }
   18949                 :            :         /* Create sub policy. */
   18950         [ #  # ]:          0 :         if (!mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_GREEN] &&
   18951                 :            :             !mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_YELLOW]) {
   18952                 :            :                 /* Reuse the first pre-allocated sub_policy. */
   18953                 :            :                 sub_policy = mtr_policy->sub_policys[domain][0];
   18954                 :          0 :                 sub_policy_idx = sub_policy->idx;
   18955                 :            :         } else {
   18956                 :          0 :                 sub_policy = mlx5_ipool_zmalloc
   18957                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   18958                 :            :                                  &sub_policy_idx);
   18959         [ #  # ]:          0 :                 if (!sub_policy ||
   18960         [ #  # ]:          0 :                     sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM) {
   18961         [ #  # ]:          0 :                         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++)
   18962                 :          0 :                                 mlx5_hrxq_release(dev, hrxq_idx[i]);
   18963                 :          0 :                         goto rss_sub_policy_error;
   18964                 :            :                 }
   18965                 :          0 :                 sub_policy->idx = sub_policy_idx;
   18966                 :          0 :                 sub_policy->main_policy = mtr_policy;
   18967                 :            :         }
   18968         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   18969         [ #  # ]:          0 :                 if (!rss_desc[i])
   18970                 :          0 :                         continue;
   18971                 :          0 :                 sub_policy->rix_hrxq[i] = hrxq_idx[i];
   18972         [ #  # ]:          0 :                 if (mtr_policy->is_hierarchy) {
   18973                 :            :                         act_cnt = &mtr_policy->act_cnt[i];
   18974                 :          0 :                         act_cnt->next_sub_policy = next_sub_policy;
   18975                 :          0 :                         mlx5_hrxq_release(dev, hrxq_idx[i]);
   18976                 :            :                 } else {
   18977                 :            :                         /*
   18978                 :            :                          * Overwrite the last action from
   18979                 :            :                          * RSS action to Queue action.
   18980                 :            :                          */
   18981                 :          0 :                         hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
   18982                 :            :                                               hrxq_idx[i]);
   18983         [ #  # ]:          0 :                         if (!hrxq) {
   18984                 :          0 :                                 DRV_LOG(ERR, "Failed to get policy hrxq");
   18985                 :          0 :                                 goto rss_sub_policy_error;
   18986                 :            :                         }
   18987                 :            :                         act_cnt = &mtr_policy->act_cnt[i];
   18988   [ #  #  #  # ]:          0 :                         if (act_cnt->rix_mark || act_cnt->modify_hdr) {
   18989                 :            :                                 memset(&dh, 0, sizeof(struct mlx5_flow_handle));
   18990         [ #  # ]:          0 :                                 if (act_cnt->rix_mark)
   18991                 :          0 :                                         wks->mark = 1;
   18992                 :          0 :                                 dh.fate_action = MLX5_FLOW_FATE_QUEUE;
   18993                 :          0 :                                 dh.rix_hrxq = hrxq_idx[i];
   18994                 :          0 :                                 flow_drv_rxq_flags_set(dev, &dh);
   18995                 :            :                         }
   18996                 :            :                 }
   18997                 :            :         }
   18998         [ #  # ]:          0 :         if (__flow_dv_create_policy_acts_rules(dev, mtr_policy,
   18999                 :            :                                                sub_policy, domain)) {
   19000                 :          0 :                 DRV_LOG(ERR, "Failed to create policy "
   19001                 :            :                         "rules for ingress domain.");
   19002                 :          0 :                 goto rss_sub_policy_error;
   19003                 :            :         }
   19004         [ #  # ]:          0 :         if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19005                 :          0 :                 i = (mtr_policy->sub_policy_num >>
   19006                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19007                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19008         [ #  # ]:          0 :                 if (i >= MLX5_MTR_RSS_MAX_SUB_POLICY) {
   19009                 :          0 :                         DRV_LOG(ERR, "No free sub-policy slot.");
   19010                 :          0 :                         goto rss_sub_policy_error;
   19011                 :            :                 }
   19012                 :          0 :                 mtr_policy->sub_policys[domain][i] = sub_policy;
   19013                 :          0 :                 i++;
   19014                 :          0 :                 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19015                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain));
   19016                 :          0 :                 mtr_policy->sub_policy_num |=
   19017                 :          0 :                         (i & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19018                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain);
   19019                 :            :         }
   19020                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19021                 :          0 :         *is_reuse = false;
   19022                 :          0 :         return sub_policy;
   19023                 :          0 : rss_sub_policy_error:
   19024         [ #  # ]:          0 :         if (sub_policy) {
   19025                 :          0 :                 __flow_dv_destroy_sub_policy_rules(dev, sub_policy);
   19026         [ #  # ]:          0 :                 if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19027                 :          0 :                         i = (mtr_policy->sub_policy_num >>
   19028                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19029                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19030                 :          0 :                         mtr_policy->sub_policys[domain][i] = NULL;
   19031                 :          0 :                         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19032                 :          0 :                                         sub_policy->idx);
   19033                 :            :                 }
   19034                 :            :         }
   19035                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19036                 :          0 :         return NULL;
   19037                 :            : }
   19038                 :            : 
   19039                 :            : /**
   19040                 :            :  * Find the policy table for prefix table with RSS.
   19041                 :            :  *
   19042                 :            :  * @param[in] dev
   19043                 :            :  *   Pointer to Ethernet device.
   19044                 :            :  * @param[in] mtr_policy
   19045                 :            :  *   Pointer to meter policy table.
   19046                 :            :  * @param[in] rss_desc
   19047                 :            :  *   Pointer to rss_desc
   19048                 :            :  * @return
   19049                 :            :  *   Pointer to table set on success, NULL otherwise and rte_errno is set.
   19050                 :            :  */
   19051                 :            : static struct mlx5_flow_meter_sub_policy *
   19052                 :          0 : flow_dv_meter_sub_policy_rss_prepare(struct rte_eth_dev *dev,
   19053                 :            :                 struct mlx5_flow_meter_policy *mtr_policy,
   19054                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS])
   19055                 :            : {
   19056                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19057                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   19058                 :            :         struct mlx5_flow_meter_info *next_fm;
   19059                 :            :         struct mlx5_flow_meter_policy *next_policy;
   19060                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy = NULL;
   19061                 :            :         struct mlx5_flow_meter_policy *policies[MLX5_MTR_CHAIN_MAX_NUM];
   19062                 :            :         struct mlx5_flow_meter_sub_policy *sub_policies[MLX5_MTR_CHAIN_MAX_NUM];
   19063                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   19064                 :            :         bool reuse_sub_policy;
   19065                 :            :         uint32_t i = 0;
   19066                 :            :         uint32_t j = 0;
   19067                 :            : 
   19068                 :            :         while (true) {
   19069                 :            :                 /* Iterate hierarchy to get all policies in this hierarchy. */
   19070                 :          0 :                 policies[i++] = mtr_policy;
   19071         [ #  # ]:          0 :                 if (!mtr_policy->is_hierarchy)
   19072                 :            :                         break;
   19073         [ #  # ]:          0 :                 if (i >= MLX5_MTR_CHAIN_MAX_NUM) {
   19074                 :          0 :                         DRV_LOG(ERR, "Exceed max meter number in hierarchy.");
   19075                 :          0 :                         return NULL;
   19076                 :            :                 }
   19077                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19078                 :          0 :                 next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, mtr_policy, NULL);
   19079                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19080         [ #  # ]:          0 :                 if (!next_fm) {
   19081                 :          0 :                         DRV_LOG(ERR, "Failed to get next meter in hierarchy.");
   19082                 :          0 :                         return NULL;
   19083                 :            :                 }
   19084                 :            :                 next_policy =
   19085                 :          0 :                         mlx5_flow_meter_policy_find(dev, next_fm->policy_id,
   19086                 :            :                                                     NULL);
   19087                 :            :                 MLX5_ASSERT(next_policy);
   19088                 :            :                 mtr_policy = next_policy;
   19089                 :            :         }
   19090         [ #  # ]:          0 :         while (i) {
   19091                 :            :                 /**
   19092                 :            :                  * From last policy to the first one in hierarchy,
   19093                 :            :                  * create / get the sub policy for each of them.
   19094                 :            :                  */
   19095                 :          0 :                 sub_policy = __flow_dv_meter_get_rss_sub_policy(dev,
   19096                 :            :                                                         policies[--i],
   19097                 :            :                                                         rss_desc,
   19098                 :            :                                                         next_sub_policy,
   19099                 :            :                                                         &reuse_sub_policy);
   19100         [ #  # ]:          0 :                 if (!sub_policy) {
   19101                 :          0 :                         DRV_LOG(ERR, "Failed to get the sub policy.");
   19102                 :          0 :                         goto err_exit;
   19103                 :            :                 }
   19104         [ #  # ]:          0 :                 if (!reuse_sub_policy)
   19105                 :          0 :                         sub_policies[j++] = sub_policy;
   19106                 :            :                 next_sub_policy = sub_policy;
   19107                 :            :         }
   19108                 :            :         return sub_policy;
   19109                 :            : err_exit:
   19110         [ #  # ]:          0 :         while (j) {
   19111                 :            :                 uint16_t sub_policy_num;
   19112                 :            : 
   19113                 :          0 :                 sub_policy = sub_policies[--j];
   19114                 :          0 :                 mtr_policy = sub_policy->main_policy;
   19115                 :          0 :                 __flow_dv_destroy_sub_policy_rules(dev, sub_policy);
   19116         [ #  # ]:          0 :                 if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19117                 :          0 :                         sub_policy_num = (mtr_policy->sub_policy_num >>
   19118                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19119                 :            :                                 MLX5_MTR_SUB_POLICY_NUM_MASK;
   19120                 :          0 :                         mtr_policy->sub_policys[domain][sub_policy_num - 1] =
   19121                 :            :                                                                         NULL;
   19122                 :          0 :                         sub_policy_num--;
   19123                 :          0 :                         mtr_policy->sub_policy_num &=
   19124                 :          0 :                                 ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19125                 :          0 :                                   (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
   19126                 :          0 :                         mtr_policy->sub_policy_num |=
   19127                 :          0 :                         (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19128                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
   19129                 :          0 :                         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19130                 :          0 :                                         sub_policy->idx);
   19131                 :            :                 }
   19132                 :            :         }
   19133                 :            :         return NULL;
   19134                 :            : }
   19135                 :            : 
   19136                 :            : /**
   19137                 :            :  * Check if need to create hierarchy tag rule.
   19138                 :            :  *
   19139                 :            :  * @param[in] priv
   19140                 :            :  *   Pointer to mlx5_priv.
   19141                 :            :  * @param[in] mtr_policy
   19142                 :            :  *   Pointer to current meter policy.
   19143                 :            :  * @param[in] src_port
   19144                 :            :  *   The src port this extra rule should use.
   19145                 :            :  * @param[out] next_fm
   19146                 :            :  *   Pointer to next meter in hierarchy.
   19147                 :            :  * @param[out] skip
   19148                 :            :  *   Indicate if skip the tag rule creation.
   19149                 :            :  * @param[out] error
   19150                 :            :  *   Perform verbose error reporting if not NULL.
   19151                 :            :  * @return
   19152                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19153                 :            :  */
   19154                 :            : static int
   19155                 :          0 : mlx5_meter_hierarchy_skip_tag_rule(struct mlx5_priv *priv,
   19156                 :            :                                    struct mlx5_flow_meter_policy *mtr_policy,
   19157                 :            :                                    int32_t src_port,
   19158                 :            :                                    struct mlx5_flow_meter_info **next_fm,
   19159                 :            :                                    bool *skip,
   19160                 :            :                                    struct rte_flow_error *error)
   19161                 :            : {
   19162                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   19163                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   19164                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_TRANSFER;
   19165                 :            :         int ret = 0;
   19166                 :            :         int i;
   19167                 :            : 
   19168                 :          0 :         *next_fm = NULL;
   19169                 :          0 :         *skip = false;
   19170                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   19171         [ #  # ]:          0 :         if (mtr_policy->is_hierarchy) {
   19172                 :          0 :                 *next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, mtr_policy, NULL);
   19173         [ #  # ]:          0 :                 if (!*next_fm) {
   19174                 :          0 :                         ret = rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   19175                 :            :                                                 NULL, "Failed to find next meter in hierarchy.");
   19176                 :          0 :                         goto exit;
   19177                 :            :                 }
   19178                 :            :         }
   19179         [ #  # ]:          0 :         if (!mtr_policy->match_port) {
   19180                 :          0 :                 *skip = true;
   19181                 :          0 :                 goto exit;
   19182                 :            :         }
   19183                 :          0 :         sub_policy = mtr_policy->sub_policys[domain][0];
   19184         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19185         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action != MLX5_FLOW_FATE_MTR &&
   19186                 :            :                     mtr_policy->act_cnt[i].fate_action != MLX5_FLOW_FATE_PORT_ID)
   19187                 :          0 :                         continue;
   19188         [ #  # ]:          0 :                 TAILQ_FOREACH(color_rule, &sub_policy->color_rules[i], next_port)
   19189         [ #  # ]:          0 :                         if (color_rule->src_port == src_port) {
   19190                 :          0 :                                 *skip = true;
   19191                 :          0 :                                 goto exit;
   19192                 :            :                         }
   19193                 :            :         }
   19194                 :          0 : exit:
   19195                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19196                 :          0 :         return ret;
   19197                 :            : }
   19198                 :            : 
   19199                 :            : /**
   19200                 :            :  * Create the sub policy tag rule for all meters in hierarchy.
   19201                 :            :  *
   19202                 :            :  * @param[in] dev
   19203                 :            :  *   Pointer to Ethernet device.
   19204                 :            :  * @param[in] fm
   19205                 :            :  *   Meter information table.
   19206                 :            :  * @param[in] src_port
   19207                 :            :  *   The src port this extra rule should use.
   19208                 :            :  * @param[in] item
   19209                 :            :  *   The src port match item.
   19210                 :            :  * @param[out] error
   19211                 :            :  *   Perform verbose error reporting if not NULL.
   19212                 :            :  * @return
   19213                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19214                 :            :  */
   19215                 :            : static int
   19216                 :          0 : flow_dv_meter_hierarchy_rule_create(struct rte_eth_dev *dev,
   19217                 :            :                                 struct mlx5_flow_meter_info *fm,
   19218                 :            :                                 int32_t src_port,
   19219                 :            :                                 const struct rte_flow_item *item,
   19220                 :            :                                 struct rte_flow_error *error)
   19221                 :            : {
   19222                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19223                 :            :         struct mlx5_flow_meter_policy *mtr_policy;
   19224                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   19225                 :          0 :         struct mlx5_flow_meter_info *next_fm = NULL;
   19226                 :            :         struct mlx5_flow_meter_policy *next_policy;
   19227                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy;
   19228                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   19229                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   19230                 :            :         struct mlx5_meter_policy_acts acts;
   19231                 :            :         uint32_t color_reg_c_idx;
   19232                 :            :         bool mtr_first = (src_port != UINT16_MAX) ? true : false;
   19233                 :          0 :         struct rte_flow_attr attr = {
   19234                 :            :                 .group = MLX5_FLOW_TABLE_LEVEL_POLICY,
   19235                 :            :                 .priority = 0,
   19236                 :            :                 .ingress = 0,
   19237                 :            :                 .egress = 0,
   19238                 :            :                 .transfer = 1,
   19239                 :            :                 .reserved = 0,
   19240                 :            :         };
   19241                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_TRANSFER;
   19242                 :            :         struct {
   19243                 :            :                 struct mlx5_flow_meter_policy *fm_policy;
   19244                 :            :                 struct mlx5_flow_meter_info *next_fm;
   19245                 :            :                 struct mlx5_sub_policy_color_rule *tag_rule[RTE_COLORS];
   19246                 :          0 :         } fm_info[MLX5_MTR_CHAIN_MAX_NUM] = { {0} };
   19247                 :            :         uint32_t fm_cnt = 0;
   19248                 :            :         uint32_t i, j;
   19249                 :            : 
   19250                 :          0 :         color_reg_c_idx = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, error);
   19251                 :            :         /* Get all fms who need to create the tag color rule. */
   19252                 :            :         do {
   19253                 :          0 :                 bool skip = false;
   19254                 :            : 
   19255                 :          0 :                 mtr_policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
   19256                 :            :                 MLX5_ASSERT(mtr_policy);
   19257         [ #  # ]:          0 :                 if (mlx5_meter_hierarchy_skip_tag_rule(priv, mtr_policy, src_port,
   19258                 :            :                                                        &next_fm, &skip, error))
   19259                 :          0 :                         goto err_exit;
   19260         [ #  # ]:          0 :                 if (!skip) {
   19261                 :          0 :                         fm_info[fm_cnt].fm_policy = mtr_policy;
   19262                 :          0 :                         fm_info[fm_cnt].next_fm = next_fm;
   19263         [ #  # ]:          0 :                         if (++fm_cnt >= MLX5_MTR_CHAIN_MAX_NUM) {
   19264                 :          0 :                                 rte_flow_error_set(error, errno,
   19265                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19266                 :            :                                         "Exceed max meter number in hierarchy.");
   19267                 :          0 :                                 goto err_exit;
   19268                 :            :                         }
   19269                 :            :                 }
   19270                 :          0 :                 fm = next_fm;
   19271         [ #  # ]:          0 :         } while (fm);
   19272                 :            :         /* Create tag color rules for all needed fms. */
   19273         [ #  # ]:          0 :         for (i = 0; i < fm_cnt; i++) {
   19274                 :            :                 void *mtr_action;
   19275                 :            : 
   19276                 :          0 :                 mtr_policy = fm_info[i].fm_policy;
   19277                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19278                 :          0 :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19279         [ #  # ]:          0 :                 for (j = 0; j < RTE_COLORS; j++) {
   19280                 :            :                         uint8_t act_n = 0;
   19281                 :            :                         struct mlx5_flow_dv_modify_hdr_resource *modify_hdr = NULL;
   19282                 :            :                         struct mlx5_flow_dv_port_id_action_resource *port_action;
   19283                 :            :                         uint8_t fate_action;
   19284                 :            : 
   19285         [ #  # ]:          0 :                         if (j == RTE_COLOR_RED) {
   19286                 :            :                                 fate_action = MLX5_FLOW_FATE_DROP;
   19287                 :            :                         } else {
   19288                 :          0 :                                 fate_action = mtr_policy->act_cnt[j].fate_action;
   19289                 :          0 :                                 modify_hdr = mtr_policy->act_cnt[j].modify_hdr;
   19290                 :          0 :                                 if (fate_action != MLX5_FLOW_FATE_MTR &&
   19291   [ #  #  #  # ]:          0 :                                     fate_action != MLX5_FLOW_FATE_PORT_ID &&
   19292                 :            :                                     fate_action != MLX5_FLOW_FATE_DROP)
   19293                 :          0 :                                         continue;
   19294                 :            :                         }
   19295                 :          0 :                         color_rule = mlx5_malloc(MLX5_MEM_ZERO,
   19296                 :            :                                                  sizeof(struct mlx5_sub_policy_color_rule),
   19297                 :            :                                                  0, SOCKET_ID_ANY);
   19298         [ #  # ]:          0 :                         if (!color_rule) {
   19299                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19300                 :          0 :                                 rte_flow_error_set(error, ENOMEM,
   19301                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   19302                 :            :                                                    "No memory to create tag color rule.");
   19303                 :          0 :                                 goto err_exit;
   19304                 :            :                         }
   19305                 :          0 :                         color_rule->src_port = src_port;
   19306                 :            :                         /* Prepare to create color rule. */
   19307         [ #  # ]:          0 :                         if (fate_action == MLX5_FLOW_FATE_MTR) {
   19308                 :          0 :                                 next_fm = fm_info[i].next_fm;
   19309         [ #  # ]:          0 :                                 if (mlx5_flow_meter_attach(priv, next_fm, &attr, error)) {
   19310                 :          0 :                                         mlx5_free(color_rule);
   19311                 :            :                                         rte_spinlock_unlock(&mtr_policy->sl);
   19312                 :          0 :                                         goto err_exit;
   19313                 :            :                                 }
   19314         [ #  # ]:          0 :                                 mtr_action = (next_fm->color_aware && j == RTE_COLOR_YELLOW) ?
   19315         [ #  # ]:          0 :                                                                         next_fm->meter_action_y :
   19316                 :            :                                                                         next_fm->meter_action_g;
   19317                 :          0 :                                 next_policy = mlx5_flow_meter_policy_find(dev, next_fm->policy_id,
   19318                 :            :                                                                           NULL);
   19319                 :            :                                 MLX5_ASSERT(next_policy);
   19320                 :          0 :                                 next_sub_policy = next_policy->sub_policys[domain][0];
   19321                 :          0 :                                 tbl_data = container_of(next_sub_policy->tbl_rsc,
   19322                 :            :                                                         struct mlx5_flow_tbl_data_entry, tbl);
   19323         [ #  # ]:          0 :                                 if (mtr_first) {
   19324                 :          0 :                                         acts.dv_actions[act_n++] = mtr_action;
   19325         [ #  # ]:          0 :                                         if (modify_hdr)
   19326                 :          0 :                                                 acts.dv_actions[act_n++] = modify_hdr->action;
   19327                 :            :                                 } else {
   19328         [ #  # ]:          0 :                                         if (modify_hdr)
   19329                 :          0 :                                                 acts.dv_actions[act_n++] = modify_hdr->action;
   19330                 :          0 :                                         acts.dv_actions[act_n++] = mtr_action;
   19331                 :            :                                 }
   19332                 :          0 :                                 acts.dv_actions[act_n++] = tbl_data->jump.action;
   19333                 :          0 :                                 acts.actions_n = act_n;
   19334         [ #  # ]:          0 :                         } else if (fate_action == MLX5_FLOW_FATE_PORT_ID) {
   19335                 :            :                                 port_action =
   19336                 :          0 :                                         mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID],
   19337                 :            :                                                        mtr_policy->act_cnt[j].rix_port_id_action);
   19338         [ #  # ]:          0 :                                 if (!port_action) {
   19339                 :          0 :                                         mlx5_free(color_rule);
   19340                 :            :                                         rte_spinlock_unlock(&mtr_policy->sl);
   19341                 :          0 :                                         goto err_exit;
   19342                 :            :                                 }
   19343         [ #  # ]:          0 :                                 if (modify_hdr)
   19344                 :          0 :                                         acts.dv_actions[act_n++] = modify_hdr->action;
   19345                 :          0 :                                 acts.dv_actions[act_n++] = port_action->action;
   19346                 :          0 :                                 acts.actions_n = act_n;
   19347                 :            :                         } else {
   19348                 :          0 :                                 acts.dv_actions[act_n++] = mtr_policy->dr_drop_action[domain];
   19349                 :          0 :                                 acts.actions_n = act_n;
   19350                 :            :                         }
   19351                 :          0 :                         fm_info[i].tag_rule[j] = color_rule;
   19352                 :          0 :                         TAILQ_INSERT_TAIL(&sub_policy->color_rules[j], color_rule, next_port);
   19353         [ #  # ]:          0 :                         if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
   19354                 :            :                                                 MLX5_MTR_POLICY_MATCHER_PRIO, sub_policy,
   19355                 :            :                                                 &attr, true, item, &color_rule->matcher, error)) {
   19356                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19357                 :          0 :                                 rte_flow_error_set(error, errno,
   19358                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19359                 :            :                                                    "Failed to create hierarchy meter matcher.");
   19360                 :          0 :                                 goto err_exit;
   19361                 :            :                         }
   19362         [ #  # ]:          0 :                         if (__flow_dv_create_policy_flow(dev, color_reg_c_idx, (enum rte_color)j,
   19363                 :            :                                                 color_rule->matcher,
   19364                 :          0 :                                                 acts.actions_n, acts.dv_actions,
   19365                 :            :                                                 true, item, &color_rule->rule, &attr)) {
   19366                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19367                 :          0 :                                 rte_flow_error_set(error, errno,
   19368                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19369                 :            :                                                    "Failed to create hierarchy meter rule.");
   19370                 :          0 :                                 goto err_exit;
   19371                 :            :                         }
   19372                 :            :                 }
   19373                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19374                 :            :         }
   19375                 :            :         return 0;
   19376                 :          0 : err_exit:
   19377         [ #  # ]:          0 :         for (i = 0; i < fm_cnt; i++) {
   19378                 :          0 :                 mtr_policy = fm_info[i].fm_policy;
   19379                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19380                 :          0 :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19381         [ #  # ]:          0 :                 for (j = 0; j < RTE_COLORS; j++) {
   19382                 :          0 :                         color_rule = fm_info[i].tag_rule[j];
   19383         [ #  # ]:          0 :                         if (!color_rule)
   19384                 :          0 :                                 continue;
   19385         [ #  # ]:          0 :                         if (color_rule->rule)
   19386                 :            :                                 mlx5_flow_os_destroy_flow(color_rule->rule);
   19387         [ #  # ]:          0 :                         if (color_rule->matcher) {
   19388                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl =
   19389                 :          0 :                                         container_of(color_rule->matcher->tbl, typeof(*tbl), tbl);
   19390                 :          0 :                                 mlx5_list_unregister(tbl->matchers, &color_rule->matcher->entry);
   19391                 :            :                         }
   19392         [ #  # ]:          0 :                         if (fm_info[i].next_fm)
   19393                 :          0 :                                 mlx5_flow_meter_detach(priv, fm_info[i].next_fm);
   19394         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[j], color_rule, next_port);
   19395                 :          0 :                         mlx5_free(color_rule);
   19396                 :            :                 }
   19397                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19398                 :            :         }
   19399                 :          0 :         return -rte_errno;
   19400                 :            : }
   19401                 :            : 
   19402                 :            : /**
   19403                 :            :  * Destroy the sub policy table with RX queue.
   19404                 :            :  *
   19405                 :            :  * @param[in] dev
   19406                 :            :  *   Pointer to Ethernet device.
   19407                 :            :  * @param[in] mtr_policy
   19408                 :            :  *   Pointer to meter policy table.
   19409                 :            :  */
   19410                 :            : static void
   19411                 :          0 : flow_dv_destroy_sub_policy_with_rxq(struct rte_eth_dev *dev,
   19412                 :            :                                     struct mlx5_flow_meter_policy *mtr_policy)
   19413                 :            : {
   19414                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19415                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   19416                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   19417                 :            :         uint32_t i, j;
   19418                 :            :         uint16_t sub_policy_num, new_policy_num;
   19419                 :            : 
   19420                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   19421         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19422      [ #  #  # ]:          0 :                 switch (mtr_policy->act_cnt[i].fate_action) {
   19423                 :          0 :                 case MLX5_FLOW_FATE_SHARED_RSS:
   19424                 :          0 :                         sub_policy_num = (mtr_policy->sub_policy_num >>
   19425                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19426                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19427                 :            :                         new_policy_num = sub_policy_num;
   19428         [ #  # ]:          0 :                         for (j = 0; j < sub_policy_num; j++) {
   19429                 :          0 :                                 sub_policy =
   19430                 :          0 :                                         mtr_policy->sub_policys[domain][j];
   19431         [ #  # ]:          0 :                                 if (sub_policy) {
   19432                 :          0 :                                         __flow_dv_destroy_sub_policy_rules(dev,
   19433                 :            :                                                 sub_policy);
   19434                 :          0 :                                 if (sub_policy !=
   19435         [ #  # ]:          0 :                                         mtr_policy->sub_policys[domain][0]) {
   19436                 :          0 :                                         mtr_policy->sub_policys[domain][j] =
   19437                 :            :                                                                 NULL;
   19438                 :          0 :                                         mlx5_ipool_free
   19439                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19440                 :          0 :                                                 sub_policy->idx);
   19441                 :          0 :                                                 new_policy_num--;
   19442                 :            :                                         }
   19443                 :            :                                 }
   19444                 :            :                         }
   19445         [ #  # ]:          0 :                         if (new_policy_num != sub_policy_num) {
   19446                 :          0 :                                 mtr_policy->sub_policy_num &=
   19447                 :            :                                 ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19448                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain));
   19449                 :          0 :                                 mtr_policy->sub_policy_num |=
   19450                 :            :                                 (new_policy_num &
   19451                 :            :                                         MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19452                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain);
   19453                 :            :                         }
   19454                 :            :                         break;
   19455                 :          0 :                 case MLX5_FLOW_FATE_QUEUE:
   19456                 :          0 :                         sub_policy = mtr_policy->sub_policys[domain][0];
   19457                 :          0 :                         __flow_dv_destroy_sub_policy_rules(dev,
   19458                 :            :                                                            sub_policy);
   19459                 :          0 :                         break;
   19460                 :            :                 default:
   19461                 :            :                         /*Other actions without queue and do nothing*/
   19462                 :            :                         break;
   19463                 :            :                 }
   19464                 :            :         }
   19465                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19466                 :          0 : }
   19467                 :            : /**
   19468                 :            :  * Check whether the DR drop action is supported on the root table or not.
   19469                 :            :  *
   19470                 :            :  * Create a simple flow with DR drop action on root table to validate
   19471                 :            :  * if DR drop action on root table is supported or not.
   19472                 :            :  *
   19473                 :            :  * @param[in] dev
   19474                 :            :  *   Pointer to rte_eth_dev structure.
   19475                 :            :  *
   19476                 :            :  * @return
   19477                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19478                 :            :  */
   19479                 :            : int
   19480                 :          0 : mlx5_flow_discover_dr_action_support(struct rte_eth_dev *dev)
   19481                 :            : {
   19482                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19483                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   19484                 :          0 :         struct mlx5_flow_dv_match_params mask = {
   19485                 :            :                 .size = sizeof(mask.buf),
   19486                 :            :         };
   19487                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19488                 :            :                 .size = sizeof(value.buf),
   19489                 :            :         };
   19490                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   19491                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   19492                 :            :                 .priority = 0,
   19493                 :            :                 .match_criteria_enable = 0,
   19494                 :            :                 .match_mask = (void *)&mask,
   19495                 :            :         };
   19496                 :            :         struct mlx5_flow_tbl_resource *tbl = NULL;
   19497                 :            :         void *matcher = NULL;
   19498                 :            :         void *flow = NULL;
   19499                 :            :         int ret = -1;
   19500                 :            : 
   19501                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, 0, 0, false, NULL,
   19502                 :            :                                         0, 0, 0, NULL);
   19503         [ #  # ]:          0 :         if (!tbl)
   19504                 :          0 :                 goto err;
   19505         [ #  # ]:          0 :         dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf);
   19506                 :            :         __flow_dv_adjust_buf_size(&mask.size, dv_attr.match_criteria_enable);
   19507                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   19508                 :            :                                                tbl->obj, &matcher);
   19509                 :            :         if (ret)
   19510                 :          0 :                 goto err;
   19511         [ #  # ]:          0 :         __flow_dv_adjust_buf_size(&value.size, dv_attr.match_criteria_enable);
   19512                 :          0 :         ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 1,
   19513                 :            :                                        &sh->dr_drop_action, &flow);
   19514                 :          0 : err:
   19515                 :            :         /*
   19516                 :            :          * If DR drop action is not supported on root table, flow create will
   19517                 :            :          * be failed with EOPNOTSUPP or EPROTONOSUPPORT.
   19518                 :            :          */
   19519         [ #  # ]:          0 :         if (!flow) {
   19520         [ #  # ]:          0 :                 if (matcher &&
   19521         [ #  # ]:          0 :                     (errno == EPROTONOSUPPORT || errno == EOPNOTSUPP))
   19522                 :          0 :                         DRV_LOG(INFO, "DR drop action is not supported in root table.");
   19523                 :            :                 else
   19524                 :          0 :                         DRV_LOG(ERR, "Unexpected error in DR drop action support detection");
   19525                 :            :                 ret = -1;
   19526                 :            :         } else {
   19527                 :            :                 claim_zero(mlx5_flow_os_destroy_flow(flow));
   19528                 :            :         }
   19529         [ #  # ]:          0 :         if (matcher)
   19530                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher));
   19531         [ #  # ]:          0 :         if (tbl)
   19532                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   19533                 :          0 :         return ret;
   19534                 :            : }
   19535                 :            : 
   19536                 :            : /**
   19537                 :            :  * Validate the batch counter support in root table.
   19538                 :            :  *
   19539                 :            :  * Create a simple flow with invalid counter and drop action on root table to
   19540                 :            :  * validate if batch counter with offset on root table is supported or not.
   19541                 :            :  *
   19542                 :            :  * @param[in] dev
   19543                 :            :  *   Pointer to rte_eth_dev structure.
   19544                 :            :  *
   19545                 :            :  * @return
   19546                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19547                 :            :  */
   19548                 :            : int
   19549                 :          0 : mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev)
   19550                 :            : {
   19551                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19552                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   19553                 :          0 :         struct mlx5_flow_dv_match_params mask = {
   19554                 :            :                 .size = sizeof(mask.buf),
   19555                 :            :         };
   19556                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19557                 :            :                 .size = sizeof(value.buf),
   19558                 :            :         };
   19559                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   19560                 :            :                 .type = IBV_FLOW_ATTR_NORMAL | IBV_FLOW_ATTR_FLAGS_EGRESS,
   19561                 :            :                 .priority = 0,
   19562                 :            :                 .match_criteria_enable = 0,
   19563                 :            :                 .match_mask = (void *)&mask,
   19564                 :            :         };
   19565                 :          0 :         void *actions[2] = { 0 };
   19566                 :            :         struct mlx5_flow_tbl_resource *tbl = NULL;
   19567                 :            :         struct mlx5_devx_obj *dcs = NULL;
   19568                 :            :         void *matcher = NULL;
   19569                 :            :         void *flow = NULL;
   19570                 :            :         int ret = -1;
   19571                 :            : 
   19572                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, 1, 0, false, NULL,
   19573                 :            :                                         0, 0, 0, NULL);
   19574         [ #  # ]:          0 :         if (!tbl)
   19575                 :          0 :                 goto err;
   19576                 :          0 :         dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0x4);
   19577         [ #  # ]:          0 :         if (!dcs)
   19578                 :          0 :                 goto err;
   19579                 :          0 :         ret = mlx5_flow_os_create_flow_action_count(dcs->obj, UINT16_MAX,
   19580                 :            :                                                     &actions[0]);
   19581                 :            :         if (ret)
   19582                 :          0 :                 goto err;
   19583         [ #  # ]:          0 :         dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf);
   19584                 :            :         __flow_dv_adjust_buf_size(&mask.size, dv_attr.match_criteria_enable);
   19585                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   19586                 :            :                                                tbl->obj, &matcher);
   19587                 :            :         if (ret)
   19588                 :          0 :                 goto err;
   19589         [ #  # ]:          0 :         __flow_dv_adjust_buf_size(&value.size, dv_attr.match_criteria_enable);
   19590                 :            :         ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 1,
   19591                 :            :                                        actions, &flow);
   19592                 :          0 : err:
   19593                 :            :         /*
   19594                 :            :          * If batch counter with offset is not supported, the driver will not
   19595                 :            :          * validate the invalid offset value, flow create should success.
   19596                 :            :          * In this case, it means batch counter is not supported in root table.
   19597                 :            :          *
   19598                 :            :          * Otherwise, if flow create is failed, counter offset is supported.
   19599                 :            :          */
   19600         [ #  # ]:          0 :         if (flow) {
   19601                 :          0 :                 DRV_LOG(INFO, "Batch counter is not supported in root "
   19602                 :            :                               "table. Switch to fallback mode.");
   19603                 :          0 :                 rte_errno = ENOTSUP;
   19604                 :            :                 ret = -rte_errno;
   19605                 :            :                 claim_zero(mlx5_flow_os_destroy_flow(flow));
   19606                 :            :         } else {
   19607                 :            :                 /* Check matcher to make sure validate fail at flow create. */
   19608   [ #  #  #  # ]:          0 :                 if (!matcher || (matcher && errno != EINVAL))
   19609                 :          0 :                         DRV_LOG(ERR, "Unexpected error in counter offset "
   19610                 :            :                                      "support detection");
   19611                 :            :                 ret = 0;
   19612                 :            :         }
   19613         [ #  # ]:          0 :         if (actions[0])
   19614                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action(actions[0]));
   19615         [ #  # ]:          0 :         if (matcher)
   19616                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher));
   19617         [ #  # ]:          0 :         if (tbl)
   19618                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   19619         [ #  # ]:          0 :         if (dcs)
   19620                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
   19621                 :          0 :         return ret;
   19622                 :            : }
   19623                 :            : 
   19624                 :            : /**
   19625                 :            :  * Query a devx counter.
   19626                 :            :  *
   19627                 :            :  * @param[in] dev
   19628                 :            :  *   Pointer to the Ethernet device structure.
   19629                 :            :  * @param[in] cnt
   19630                 :            :  *   Index to the flow counter.
   19631                 :            :  * @param[in] clear
   19632                 :            :  *   Set to clear the counter statistics.
   19633                 :            :  * @param[out] pkts
   19634                 :            :  *   The statistics value of packets.
   19635                 :            :  * @param[out] bytes
   19636                 :            :  *   The statistics value of bytes.
   19637                 :            :  *
   19638                 :            :  * @return
   19639                 :            :  *   0 on success, otherwise return -1.
   19640                 :            :  */
   19641                 :            : static int
   19642                 :          0 : flow_dv_counter_query(struct rte_eth_dev *dev, uint32_t counter, bool clear,
   19643                 :            :                       uint64_t *pkts, uint64_t *bytes, void **action)
   19644                 :            : {
   19645                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19646                 :            :         struct mlx5_flow_counter *cnt;
   19647                 :            :         uint64_t inn_pkts, inn_bytes;
   19648                 :            :         int ret;
   19649                 :            : 
   19650         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
   19651                 :            :                 return -1;
   19652                 :            : 
   19653                 :          0 :         ret = _flow_dv_query_count(dev, counter, &inn_pkts, &inn_bytes);
   19654         [ #  # ]:          0 :         if (ret)
   19655                 :            :                 return -1;
   19656                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, NULL);
   19657         [ #  # ]:          0 :         if (cnt && action)
   19658                 :          0 :                 *action = cnt->action;
   19659                 :            : 
   19660                 :          0 :         *pkts = inn_pkts - cnt->hits;
   19661                 :          0 :         *bytes = inn_bytes - cnt->bytes;
   19662         [ #  # ]:          0 :         if (clear) {
   19663                 :          0 :                 cnt->hits = inn_pkts;
   19664                 :          0 :                 cnt->bytes = inn_bytes;
   19665                 :            :         }
   19666                 :            :         return 0;
   19667                 :            : }
   19668                 :            : 
   19669                 :            : /**
   19670                 :            :  * Get aged-out flows.
   19671                 :            :  *
   19672                 :            :  * @param[in] dev
   19673                 :            :  *   Pointer to the Ethernet device structure.
   19674                 :            :  * @param[in] context
   19675                 :            :  *   The address of an array of pointers to the aged-out flows contexts.
   19676                 :            :  * @param[in] nb_contexts
   19677                 :            :  *   The length of context array pointers.
   19678                 :            :  * @param[out] error
   19679                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19680                 :            :  *   error only.
   19681                 :            :  *
   19682                 :            :  * @return
   19683                 :            :  *   how many contexts get in success, otherwise negative errno value.
   19684                 :            :  *   if nb_contexts is 0, return the amount of all aged contexts.
   19685                 :            :  *   if nb_contexts is not 0 , return the amount of aged flows reported
   19686                 :            :  *   in the context array.
   19687                 :            :  * @note: only stub for now
   19688                 :            :  */
   19689                 :            : static int
   19690                 :          0 : flow_dv_get_aged_flows(struct rte_eth_dev *dev,
   19691                 :            :                     void **context,
   19692                 :            :                     uint32_t nb_contexts,
   19693                 :            :                     struct rte_flow_error *error)
   19694                 :            : {
   19695                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19696                 :            :         struct mlx5_age_info *age_info;
   19697                 :            :         struct mlx5_age_param *age_param;
   19698                 :            :         struct mlx5_flow_counter *counter;
   19699                 :            :         struct mlx5_aso_age_action *act;
   19700                 :            :         int nb_flows = 0;
   19701                 :            : 
   19702         [ #  # ]:          0 :         if (nb_contexts && !context)
   19703                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   19704                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   19705                 :            :                                           NULL, "empty context");
   19706                 :          0 :         age_info = GET_PORT_AGE_INFO(priv);
   19707                 :          0 :         rte_spinlock_lock(&age_info->aged_sl);
   19708         [ #  # ]:          0 :         LIST_FOREACH(act, &age_info->aged_aso, next) {
   19709                 :          0 :                 nb_flows++;
   19710         [ #  # ]:          0 :                 if (nb_contexts) {
   19711                 :          0 :                         context[nb_flows - 1] = act->age_params.context;
   19712         [ #  # ]:          0 :                         if (!(--nb_contexts))
   19713                 :            :                                 break;
   19714                 :            :                 }
   19715                 :            :         }
   19716         [ #  # ]:          0 :         TAILQ_FOREACH(counter, &age_info->aged_counters, next) {
   19717                 :          0 :                 nb_flows++;
   19718         [ #  # ]:          0 :                 if (nb_contexts) {
   19719                 :            :                         age_param = MLX5_CNT_TO_AGE(counter);
   19720                 :          0 :                         context[nb_flows - 1] = age_param->context;
   19721         [ #  # ]:          0 :                         if (!(--nb_contexts))
   19722                 :            :                                 break;
   19723                 :            :                 }
   19724                 :            :         }
   19725                 :            :         rte_spinlock_unlock(&age_info->aged_sl);
   19726                 :          0 :         MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER);
   19727                 :          0 :         return nb_flows;
   19728                 :            : }
   19729                 :            : 
   19730                 :            : /*
   19731                 :            :  * Mutex-protected thunk to lock-free flow_dv_counter_alloc().
   19732                 :            :  */
   19733                 :            : static uint32_t
   19734                 :          0 : flow_dv_counter_allocate(struct rte_eth_dev *dev)
   19735                 :            : {
   19736                 :          0 :         return flow_dv_counter_alloc(dev, 0);
   19737                 :            : }
   19738                 :            : 
   19739                 :            : /**
   19740                 :            :  * Validate indirect action.
   19741                 :            :  * Dispatcher for action type specific validation.
   19742                 :            :  *
   19743                 :            :  * @param[in] dev
   19744                 :            :  *   Pointer to the Ethernet device structure.
   19745                 :            :  * @param[in] conf
   19746                 :            :  *   Indirect action configuration.
   19747                 :            :  * @param[in] action
   19748                 :            :  *   The indirect action object to validate.
   19749                 :            :  * @param[out] error
   19750                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19751                 :            :  *   error only.
   19752                 :            :  *
   19753                 :            :  * @return
   19754                 :            :  *   0 on success, otherwise negative errno value.
   19755                 :            :  */
   19756                 :            : int
   19757                 :          0 : flow_dv_action_validate(struct rte_eth_dev *dev,
   19758                 :            :                         const struct rte_flow_indir_action_conf *conf,
   19759                 :            :                         const struct rte_flow_action *action,
   19760                 :            :                         struct rte_flow_error *err)
   19761                 :            : {
   19762                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19763                 :            :         /* called from RTE API */
   19764                 :            : 
   19765                 :            :         RTE_SET_USED(conf);
   19766   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   19767                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   19768                 :            :                 /*
   19769                 :            :                  * priv->obj_ops is set according to driver capabilities.
   19770                 :            :                  * When DevX capabilities are
   19771                 :            :                  * sufficient, it is set to devx_obj_ops.
   19772                 :            :                  * Otherwise, it is set to ibv_obj_ops.
   19773                 :            :                  * ibv_obj_ops doesn't support ind_table_modify operation.
   19774                 :            :                  * In this case the indirect RSS action can't be used.
   19775                 :            :                  */
   19776         [ #  # ]:          0 :                 if (priv->obj_ops.ind_table_modify == NULL)
   19777                 :          0 :                         return rte_flow_error_set
   19778                 :            :                                         (err, ENOTSUP,
   19779                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   19780                 :            :                                          NULL,
   19781                 :            :                                          "Indirect RSS action not supported");
   19782                 :          0 :                 return mlx5_validate_action_rss(dev, action, err);
   19783                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   19784         [ #  # ]:          0 :                 if (!priv->sh->aso_age_mng)
   19785                 :          0 :                         return rte_flow_error_set(err, ENOTSUP,
   19786                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   19787                 :            :                                                 NULL,
   19788                 :            :                                                 "Indirect age action not supported");
   19789                 :          0 :                 return flow_dv_validate_action_age(0, action, dev, err);
   19790                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   19791                 :          0 :                 return flow_dv_validate_action_count(dev, true, 0, false, err);
   19792                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   19793         [ #  # ]:          0 :                 if (!priv->sh->ct_aso_en)
   19794                 :          0 :                         return rte_flow_error_set(err, ENOTSUP,
   19795                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19796                 :            :                                         "ASO CT is not supported");
   19797                 :          0 :                 return mlx5_validate_action_ct(dev, action->conf, err);
   19798                 :          0 :         default:
   19799                 :          0 :                 return rte_flow_error_set(err, ENOTSUP,
   19800                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   19801                 :            :                                           NULL,
   19802                 :            :                                           "action type not supported");
   19803                 :            :         }
   19804                 :            : }
   19805                 :            : 
   19806                 :            : /*
   19807                 :            :  * Check if the RSS configurations for colors of a meter policy match
   19808                 :            :  * each other, except the queues.
   19809                 :            :  *
   19810                 :            :  * @param[in] r1
   19811                 :            :  *   Pointer to the first RSS flow action.
   19812                 :            :  * @param[in] r2
   19813                 :            :  *   Pointer to the second RSS flow action.
   19814                 :            :  *
   19815                 :            :  * @return
   19816                 :            :  *   0 on match, 1 on conflict.
   19817                 :            :  */
   19818                 :            : static inline int
   19819                 :          0 : flow_dv_mtr_policy_rss_compare(const struct rte_flow_action_rss *r1,
   19820                 :            :                                const struct rte_flow_action_rss *r2)
   19821                 :            : {
   19822         [ #  # ]:          0 :         if (r1 == NULL || r2 == NULL)
   19823                 :            :                 return 0;
   19824   [ #  #  #  #  :          0 :         if (!(r1->level <= 1 && r2->level <= 1) &&
                   #  # ]
   19825         [ #  # ]:          0 :             !(r1->level > 1 && r2->level > 1))
   19826                 :            :                 return 1;
   19827         [ #  # ]:          0 :         if (r1->func != r2->func)
   19828                 :            :                 return 1;
   19829         [ #  # ]:          0 :         if (r1->types != r2->types &&
   19830         [ #  # ]:          0 :             !((r1->types == 0 || r1->types == RTE_ETH_RSS_IP) &&
   19831         [ #  # ]:          0 :               (r2->types == 0 || r2->types == RTE_ETH_RSS_IP)))
   19832                 :            :                 return 1;
   19833   [ #  #  #  # ]:          0 :         if (r1->key || r2->key) {
   19834         [ #  # ]:          0 :                 const void *key1 = r1->key ? r1->key : rss_hash_default_key;
   19835         [ #  # ]:          0 :                 const void *key2 = r2->key ? r2->key : rss_hash_default_key;
   19836                 :            : 
   19837         [ #  # ]:          0 :                 if (memcmp(key1, key2, MLX5_RSS_HASH_KEY_LEN))
   19838                 :          0 :                         return 1;
   19839                 :            :         }
   19840                 :            :         return 0;
   19841                 :            : }
   19842                 :            : 
   19843                 :            : /**
   19844                 :            :  * Validate the meter hierarchy chain for meter policy.
   19845                 :            :  *
   19846                 :            :  * @param[in] dev
   19847                 :            :  *   Pointer to the Ethernet device structure.
   19848                 :            :  * @param[in] meter_id
   19849                 :            :  *   Meter id.
   19850                 :            :  * @param[in] action_flags
   19851                 :            :  *   Holds the actions detected until now.
   19852                 :            :  * @param[out] is_rss
   19853                 :            :  *   Is RSS or not.
   19854                 :            :  * @param[out] hierarchy_domain
   19855                 :            :  *   The domain bitmap for hierarchy policy.
   19856                 :            :  * @param[out] error
   19857                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19858                 :            :  *   error only.
   19859                 :            :  *
   19860                 :            :  * @return
   19861                 :            :  *   0 on success, otherwise negative errno value with error set.
   19862                 :            :  */
   19863                 :            : static int
   19864                 :          0 : flow_dv_validate_policy_mtr_hierarchy(struct rte_eth_dev *dev,
   19865                 :            :                                   uint32_t meter_id,
   19866                 :            :                                   uint64_t action_flags,
   19867                 :            :                                   bool *is_rss,
   19868                 :            :                                   uint8_t *hierarchy_domain,
   19869                 :            :                                   struct rte_mtr_error *error)
   19870                 :            : {
   19871                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19872                 :            :         struct mlx5_flow_meter_info *fm;
   19873                 :            :         struct mlx5_flow_meter_policy *policy;
   19874                 :            :         uint8_t cnt = 1;
   19875                 :            : 
   19876         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
   19877                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   19878                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   19879                 :            :                                         RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
   19880                 :            :                                         NULL,
   19881                 :            :                                         "Multiple fate actions not supported.");
   19882                 :          0 :         *hierarchy_domain = 0;
   19883                 :          0 :         fm = mlx5_flow_meter_find(priv, meter_id, NULL);
   19884                 :            :         while (true) {
   19885         [ #  # ]:          0 :                 if (!fm)
   19886                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19887                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19888                 :            :                                         "Meter not found in meter hierarchy.");
   19889         [ #  # ]:          0 :                 if (fm->def_policy)
   19890                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19891                 :            :                                         RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19892                 :            :                         "Non termination meter not supported in hierarchy.");
   19893         [ #  # ]:          0 :                 if (!fm->shared)
   19894                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19895                 :            :                                         RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19896                 :            :                                         "Only shared meter supported in hierarchy.");
   19897                 :          0 :                 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
   19898                 :            :                 MLX5_ASSERT(policy);
   19899                 :            :                 /**
   19900                 :            :                  * Only inherit the supported domains of the first meter in
   19901                 :            :                  * hierarchy.
   19902                 :            :                  * One meter supports at least one domain.
   19903                 :            :                  */
   19904         [ #  # ]:          0 :                 if (!*hierarchy_domain) {
   19905         [ #  # ]:          0 :                         if (policy->transfer)
   19906                 :          0 :                                 *hierarchy_domain |=
   19907                 :            :                                                 MLX5_MTR_DOMAIN_TRANSFER_BIT;
   19908         [ #  # ]:          0 :                         if (policy->ingress)
   19909                 :          0 :                                 *hierarchy_domain |=
   19910                 :            :                                                 MLX5_MTR_DOMAIN_INGRESS_BIT;
   19911         [ #  # ]:          0 :                         if (policy->egress)
   19912                 :          0 :                                 *hierarchy_domain |= MLX5_MTR_DOMAIN_EGRESS_BIT;
   19913                 :            :                 }
   19914         [ #  # ]:          0 :                 if (!policy->is_hierarchy) {
   19915                 :          0 :                         *is_rss = policy->is_rss;
   19916                 :            :                         break;
   19917                 :            :                 }
   19918                 :          0 :                 rte_spinlock_lock(&policy->sl);
   19919                 :          0 :                 fm = mlx5_flow_meter_hierarchy_next_meter(priv, policy, NULL);
   19920                 :            :                 rte_spinlock_unlock(&policy->sl);
   19921         [ #  # ]:          0 :                 if (++cnt >= MLX5_MTR_CHAIN_MAX_NUM)
   19922                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19923                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
   19924                 :            :                                         "Exceed max hierarchy meter number.");
   19925                 :            :         }
   19926                 :          0 :         return 0;
   19927                 :            : }
   19928                 :            : 
   19929                 :            : /**
   19930                 :            :  * Validate meter policy actions.
   19931                 :            :  * Dispatcher for action type specific validation.
   19932                 :            :  *
   19933                 :            :  * @param[in] dev
   19934                 :            :  *   Pointer to the Ethernet device structure.
   19935                 :            :  * @param[in] action
   19936                 :            :  *   The meter policy action object to validate.
   19937                 :            :  * @param[in] attr
   19938                 :            :  *   Attributes of flow to determine steering domain.
   19939                 :            :  * @param[out] error
   19940                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19941                 :            :  *   error only.
   19942                 :            :  *
   19943                 :            :  * @return
   19944                 :            :  *   0 on success, otherwise negative errno value.
   19945                 :            :  */
   19946                 :            : static int
   19947                 :          0 : flow_dv_validate_mtr_policy_acts(struct rte_eth_dev *dev,
   19948                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
   19949                 :            :                         struct rte_flow_attr *attr,
   19950                 :            :                         bool *is_rss,
   19951                 :            :                         uint8_t *domain_bitmap,
   19952                 :            :                         uint8_t *policy_mode,
   19953                 :            :                         struct rte_mtr_error *error)
   19954                 :            : {
   19955                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19956                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
   19957                 :            :         const struct rte_flow_action *act;
   19958                 :          0 :         uint64_t action_flags[RTE_COLORS] = {0};
   19959                 :            :         int actions_n;
   19960                 :            :         int i, ret;
   19961                 :            :         struct rte_flow_error flow_err;
   19962                 :          0 :         uint8_t domain_color[RTE_COLORS] = {0};
   19963                 :            :         uint8_t def_domain = MLX5_MTR_ALL_DOMAIN_BIT;
   19964                 :          0 :         uint8_t hierarchy_domain = 0;
   19965                 :            :         const struct rte_flow_action_meter *mtr;
   19966                 :            :         const struct rte_flow_action_meter *next_mtr = NULL;
   19967                 :            :         bool def_green = false;
   19968                 :            :         bool def_yellow = false;
   19969                 :          0 :         const struct rte_flow_action_rss *rss_color[RTE_COLORS] = {NULL};
   19970                 :            :         /* Called from RTE API */
   19971   [ #  #  #  #  :          0 :         bool is_root = !(attr->group || (attr->transfer && priv->fdb_def_rule));
                   #  # ]
   19972                 :            : 
   19973         [ #  # ]:          0 :         if (!dev_conf->dv_esw_en)
   19974                 :            :                 def_domain &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
   19975                 :          0 :         *domain_bitmap = def_domain;
   19976                 :            :         /* Red color could only support DROP action. */
   19977         [ #  # ]:          0 :         if (!actions[RTE_COLOR_RED] ||
   19978         [ #  # ]:          0 :             actions[RTE_COLOR_RED]->type != RTE_FLOW_ACTION_TYPE_DROP)
   19979                 :          0 :                 return -rte_mtr_error_set(error, ENOTSUP,
   19980                 :            :                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   19981                 :            :                                 NULL, "Red color only supports drop action.");
   19982                 :            :         /*
   19983                 :            :          * Check default policy actions:
   19984                 :            :          * Green / Yellow: no action, Red: drop action
   19985                 :            :          * Either G or Y will trigger default policy actions to be created.
   19986                 :            :          */
   19987         [ #  # ]:          0 :         if (!actions[RTE_COLOR_GREEN] ||
   19988         [ #  # ]:          0 :             actions[RTE_COLOR_GREEN]->type == RTE_FLOW_ACTION_TYPE_END)
   19989                 :            :                 def_green = true;
   19990         [ #  # ]:          0 :         if (!actions[RTE_COLOR_YELLOW] ||
   19991         [ #  # ]:          0 :             actions[RTE_COLOR_YELLOW]->type == RTE_FLOW_ACTION_TYPE_END)
   19992                 :            :                 def_yellow = true;
   19993         [ #  # ]:          0 :         if (def_green && def_yellow) {
   19994                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_DEF;
   19995                 :          0 :                 return 0;
   19996         [ #  # ]:          0 :         } else if (!def_green && def_yellow) {
   19997                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_OG;
   19998         [ #  # ]:          0 :         } else if (def_green && !def_yellow) {
   19999                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_OY;
   20000                 :            :         } else {
   20001                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_ALL;
   20002                 :            :         }
   20003                 :            :         /* Set to empty string in case of NULL pointer access by user. */
   20004                 :          0 :         flow_err.message = "";
   20005         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   20006                 :          0 :                 act = actions[i];
   20007                 :          0 :                 for (action_flags[i] = 0, actions_n = 0;
   20008   [ #  #  #  # ]:          0 :                      act && act->type != RTE_FLOW_ACTION_TYPE_END;
   20009                 :          0 :                      act++) {
   20010         [ #  # ]:          0 :                         if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
   20011                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20012                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20013                 :            :                                           NULL, "too many actions");
   20014   [ #  #  #  #  :          0 :                         switch (act->type) {
          #  #  #  #  #  
                      # ]
   20015                 :          0 :                         case RTE_FLOW_ACTION_TYPE_PORT_ID:
   20016                 :            :                         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   20017         [ #  # ]:          0 :                                 if (!dev_conf->dv_esw_en)
   20018                 :          0 :                                         return -rte_mtr_error_set(error,
   20019                 :            :                                         ENOTSUP,
   20020                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20021                 :            :                                         NULL, "PORT action validate check"
   20022                 :            :                                         " fail for ESW disable");
   20023                 :          0 :                                 ret = flow_dv_validate_action_port_id(dev,
   20024                 :            :                                                 action_flags[i],
   20025                 :            :                                                 act, attr, &flow_err);
   20026         [ #  # ]:          0 :                                 if (ret)
   20027                 :          0 :                                         return -rte_mtr_error_set(error,
   20028                 :            :                                         ENOTSUP,
   20029                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20030         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20031                 :            :                                         flow_err.message :
   20032                 :            :                                         "PORT action validate check fail");
   20033                 :          0 :                                 ++actions_n;
   20034                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_PORT_ID;
   20035                 :          0 :                                 break;
   20036                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MARK:
   20037                 :          0 :                                 ret = flow_dv_validate_action_mark(dev, act,
   20038                 :            :                                                            action_flags[i],
   20039                 :            :                                                            attr, &flow_err);
   20040         [ #  # ]:          0 :                                 if (ret < 0)
   20041                 :          0 :                                         return -rte_mtr_error_set(error,
   20042                 :            :                                         ENOTSUP,
   20043                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20044         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20045                 :            :                                         flow_err.message :
   20046                 :            :                                         "Mark action validate check fail");
   20047         [ #  # ]:          0 :                                 if (dev_conf->dv_xmeta_en !=
   20048                 :            :                                         MLX5_XMETA_MODE_LEGACY)
   20049                 :          0 :                                         return -rte_mtr_error_set(error,
   20050                 :            :                                         ENOTSUP,
   20051                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20052                 :            :                                         NULL, "Extend MARK action is "
   20053                 :            :                                         "not supported. Please try use "
   20054                 :            :                                         "default policy for meter.");
   20055                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_MARK;
   20056                 :          0 :                                 ++actions_n;
   20057                 :          0 :                                 break;
   20058                 :          0 :                         case RTE_FLOW_ACTION_TYPE_SET_TAG:
   20059                 :          0 :                                 ret = flow_dv_validate_action_set_tag(dev,
   20060                 :            :                                                         act, action_flags[i],
   20061                 :            :                                                         attr, &flow_err);
   20062         [ #  # ]:          0 :                                 if (ret)
   20063                 :          0 :                                         return -rte_mtr_error_set(error,
   20064                 :            :                                         ENOTSUP,
   20065                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20066         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20067                 :            :                                         flow_err.message :
   20068                 :            :                                         "Set tag action validate check fail");
   20069                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_SET_TAG;
   20070                 :          0 :                                 ++actions_n;
   20071                 :          0 :                                 break;
   20072                 :          0 :                         case RTE_FLOW_ACTION_TYPE_DROP:
   20073                 :          0 :                                 ret = mlx5_flow_validate_action_drop
   20074                 :            :                                         (dev, false, attr, &flow_err);
   20075         [ #  # ]:          0 :                                 if (ret < 0)
   20076                 :          0 :                                         return -rte_mtr_error_set(error,
   20077                 :            :                                         ENOTSUP,
   20078                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20079         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20080                 :            :                                         flow_err.message :
   20081                 :            :                                         "Drop action validate check fail");
   20082                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_DROP;
   20083                 :          0 :                                 ++actions_n;
   20084                 :          0 :                                 break;
   20085                 :          0 :                         case RTE_FLOW_ACTION_TYPE_QUEUE:
   20086                 :            :                                 /*
   20087                 :            :                                  * Check whether extensive
   20088                 :            :                                  * metadata feature is engaged.
   20089                 :            :                                  */
   20090         [ #  # ]:          0 :                                 if (dev_conf->dv_flow_en &&
   20091         [ #  # ]:          0 :                                     (dev_conf->dv_xmeta_en !=
   20092         [ #  # ]:          0 :                                      MLX5_XMETA_MODE_LEGACY) &&
   20093                 :          0 :                                     mlx5_flow_ext_mreg_supported(dev))
   20094                 :          0 :                                         return -rte_mtr_error_set(error,
   20095                 :            :                                           ENOTSUP,
   20096                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20097                 :            :                                           NULL, "Queue action with meta "
   20098                 :            :                                           "is not supported. Please try use "
   20099                 :            :                                           "default policy for meter.");
   20100                 :          0 :                                 ret = mlx5_flow_validate_action_queue(act,
   20101                 :            :                                                         action_flags[i], dev,
   20102                 :            :                                                         attr, &flow_err);
   20103         [ #  # ]:          0 :                                 if (ret < 0)
   20104                 :          0 :                                         return -rte_mtr_error_set(error,
   20105                 :            :                                           ENOTSUP,
   20106                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20107         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20108                 :            :                                           flow_err.message :
   20109                 :            :                                           "Queue action validate check fail");
   20110                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_QUEUE;
   20111                 :          0 :                                 ++actions_n;
   20112                 :          0 :                                 break;
   20113                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RSS:
   20114         [ #  # ]:          0 :                                 if (dev_conf->dv_flow_en &&
   20115         [ #  # ]:          0 :                                     (dev_conf->dv_xmeta_en !=
   20116         [ #  # ]:          0 :                                      MLX5_XMETA_MODE_LEGACY) &&
   20117                 :          0 :                                     mlx5_flow_ext_mreg_supported(dev))
   20118                 :          0 :                                         return -rte_mtr_error_set(error,
   20119                 :            :                                           ENOTSUP,
   20120                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20121                 :            :                                           NULL, "RSS action with meta "
   20122                 :            :                                           "is not supported. Please try use "
   20123                 :            :                                           "default policy for meter.");
   20124                 :          0 :                                 ret = mlx5_validate_action_rss(dev, act,
   20125                 :            :                                                                &flow_err);
   20126         [ #  # ]:          0 :                                 if (ret < 0)
   20127                 :          0 :                                         return -rte_mtr_error_set(error,
   20128                 :            :                                           ENOTSUP,
   20129                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20130         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20131                 :            :                                           flow_err.message :
   20132                 :            :                                           "RSS action validate check fail");
   20133                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_RSS;
   20134                 :          0 :                                 ++actions_n;
   20135                 :            :                                 /* Either G or Y will set the RSS. */
   20136                 :          0 :                                 rss_color[i] = act->conf;
   20137                 :          0 :                                 break;
   20138                 :          0 :                         case RTE_FLOW_ACTION_TYPE_JUMP:
   20139                 :          0 :                                 ret = flow_dv_validate_action_jump(dev,
   20140                 :            :                                         NULL, act, action_flags[i],
   20141                 :            :                                         attr, true, &flow_err);
   20142         [ #  # ]:          0 :                                 if (ret)
   20143                 :          0 :                                         return -rte_mtr_error_set(error,
   20144                 :            :                                           ENOTSUP,
   20145                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20146         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20147                 :            :                                           flow_err.message :
   20148                 :            :                                           "Jump action validate check fail");
   20149                 :          0 :                                 ++actions_n;
   20150                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_JUMP;
   20151                 :          0 :                                 break;
   20152                 :          0 :                         case RTE_FLOW_ACTION_TYPE_METER:
   20153                 :          0 :                                 mtr = act->conf;
   20154   [ #  #  #  # ]:          0 :                                 if (next_mtr && next_mtr->mtr_id != mtr->mtr_id)
   20155                 :          0 :                                         return -rte_mtr_error_set(error, ENOTSUP,
   20156                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
   20157                 :            :                                                 "Green and Yellow must use the same meter.");
   20158                 :          0 :                                 ret = flow_dv_validate_policy_mtr_hierarchy(dev,
   20159                 :          0 :                                                         mtr->mtr_id,
   20160                 :            :                                                         action_flags[i],
   20161                 :            :                                                         is_rss,
   20162                 :            :                                                         &hierarchy_domain,
   20163                 :            :                                                         error);
   20164         [ #  # ]:          0 :                                 if (ret)
   20165                 :          0 :                                         return ret;
   20166                 :          0 :                                 ++actions_n;
   20167                 :          0 :                                 action_flags[i] |=
   20168                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
   20169                 :            :                                 next_mtr = mtr;
   20170                 :          0 :                                 break;
   20171                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   20172                 :          0 :                                 ret = flow_dv_validate_action_modify_field(dev,
   20173                 :            :                                         action_flags[i], act, attr, is_root, &flow_err);
   20174         [ #  # ]:          0 :                                 if (ret < 0)
   20175                 :          0 :                                         return -rte_mtr_error_set(error,
   20176                 :            :                                           ENOTSUP,
   20177                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20178         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20179                 :            :                                           flow_err.message :
   20180                 :            :                                           "Modify field action validate check fail");
   20181                 :          0 :                                 ++actions_n;
   20182                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   20183                 :          0 :                                 break;
   20184                 :            :                         default:
   20185                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20186                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20187                 :            :                                         NULL,
   20188                 :            :                                         "Doesn't support optional action");
   20189                 :            :                         }
   20190                 :            :                 }
   20191         [ #  # ]:          0 :                 if (action_flags[i] & MLX5_FLOW_ACTION_PORT_ID) {
   20192                 :          0 :                         domain_color[i] = MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20193         [ #  # ]:          0 :                 } else if ((action_flags[i] &
   20194                 :          0 :                           (MLX5_FLOW_ACTION_RSS | MLX5_FLOW_ACTION_QUEUE)) ||
   20195         [ #  # ]:          0 :                           (action_flags[i] & MLX5_FLOW_ACTION_MARK)) {
   20196                 :            :                         /*
   20197                 :            :                          * Only support MLX5_XMETA_MODE_LEGACY
   20198                 :            :                          * so MARK action is only in ingress domain.
   20199                 :            :                          */
   20200                 :          0 :                         domain_color[i] = MLX5_MTR_DOMAIN_INGRESS_BIT;
   20201                 :            :                 } else {
   20202                 :          0 :                         domain_color[i] = def_domain;
   20203         [ #  # ]:          0 :                         if (action_flags[i] &&
   20204         [ #  # ]:          0 :                             !(action_flags[i] & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   20205                 :          0 :                                 domain_color[i] &=
   20206                 :            :                                 ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20207                 :            :                 }
   20208         [ #  # ]:          0 :                 if (action_flags[i] &
   20209                 :            :                     MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
   20210                 :          0 :                         domain_color[i] &= hierarchy_domain;
   20211                 :            :                 /*
   20212                 :            :                  * Non-termination actions only support NIC Tx domain.
   20213                 :            :                  * The adjustion should be skipped when there is no
   20214                 :            :                  * action or only END is provided. The default domains
   20215                 :            :                  * bit-mask is set to find the MIN intersection.
   20216                 :            :                  * The action flags checking should also be skipped.
   20217                 :            :                  */
   20218         [ #  # ]:          0 :                 if ((def_green && i == RTE_COLOR_GREEN) ||
   20219         [ #  # ]:          0 :                     (def_yellow && i == RTE_COLOR_YELLOW))
   20220                 :          0 :                         continue;
   20221                 :            :                 /*
   20222                 :            :                  * Validate the drop action mutual exclusion
   20223                 :            :                  * with other actions. Drop action is mutually-exclusive
   20224                 :            :                  * with any other action, except for Count action.
   20225                 :            :                  */
   20226         [ #  # ]:          0 :                 if ((action_flags[i] & MLX5_FLOW_ACTION_DROP) &&
   20227         [ #  # ]:          0 :                     (action_flags[i] & ~MLX5_FLOW_ACTION_DROP)) {
   20228                 :          0 :                         return -rte_mtr_error_set(error, ENOTSUP,
   20229                 :            :                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   20230                 :            :                                 NULL, "Drop action is mutually-exclusive "
   20231                 :            :                                 "with any other action");
   20232                 :            :                 }
   20233                 :            :                 /* Eswitch has few restrictions on using items and actions */
   20234         [ #  # ]:          0 :                 if (domain_color[i] & MLX5_MTR_DOMAIN_TRANSFER_BIT) {
   20235         [ #  # ]:          0 :                         if (!mlx5_flow_ext_mreg_supported(dev) &&
   20236         [ #  # ]:          0 :                             action_flags[i] & MLX5_FLOW_ACTION_MARK)
   20237                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20238                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20239                 :            :                                         NULL, "unsupported action MARK");
   20240         [ #  # ]:          0 :                         if (action_flags[i] & MLX5_FLOW_ACTION_QUEUE)
   20241                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20242                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20243                 :            :                                         NULL, "unsupported action QUEUE");
   20244         [ #  # ]:          0 :                         if (action_flags[i] & MLX5_FLOW_ACTION_RSS)
   20245                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20246                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20247                 :            :                                         NULL, "unsupported action RSS");
   20248         [ #  # ]:          0 :                         if (!(action_flags[i] & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   20249                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20250                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20251                 :            :                                         NULL, "no fate action is found");
   20252                 :            :                 } else {
   20253   [ #  #  #  # ]:          0 :                         if (!(action_flags[i] & MLX5_FLOW_FATE_ACTIONS) &&
   20254                 :            :                             (domain_color[i] & MLX5_MTR_DOMAIN_INGRESS_BIT)) {
   20255         [ #  # ]:          0 :                                 if ((domain_color[i] &
   20256                 :            :                                      MLX5_MTR_DOMAIN_EGRESS_BIT))
   20257                 :          0 :                                         domain_color[i] =
   20258                 :            :                                                 MLX5_MTR_DOMAIN_EGRESS_BIT;
   20259                 :            :                                 else
   20260                 :          0 :                                         return -rte_mtr_error_set(error,
   20261                 :            :                                                 ENOTSUP,
   20262                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   20263                 :            :                                                 NULL,
   20264                 :            :                                                 "no fate action is found");
   20265                 :            :                         }
   20266                 :            :                 }
   20267                 :            :         }
   20268   [ #  #  #  # ]:          0 :         if (next_mtr && *policy_mode == MLX5_MTR_POLICY_MODE_ALL) {
   20269                 :            :                 uint64_t hierarchy_type_flag =
   20270                 :            :                         MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY | MLX5_FLOW_ACTION_JUMP;
   20271         [ #  # ]:          0 :                 if (!(action_flags[RTE_COLOR_GREEN] & hierarchy_type_flag) ||
   20272         [ #  # ]:          0 :                     !(action_flags[RTE_COLOR_YELLOW] & hierarchy_type_flag))
   20273                 :          0 :                         return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_POLICY,
   20274                 :            :                                                   NULL,
   20275                 :            :                                                   "Unsupported action in meter hierarchy.");
   20276                 :            :         }
   20277                 :            :         /* If both colors have RSS, the attributes should be the same. */
   20278         [ #  # ]:          0 :         if (flow_dv_mtr_policy_rss_compare(rss_color[RTE_COLOR_GREEN],
   20279                 :            :                                            rss_color[RTE_COLOR_YELLOW]))
   20280                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   20281                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20282                 :            :                                           NULL, "policy RSS attr conflict");
   20283   [ #  #  #  # ]:          0 :         if (rss_color[RTE_COLOR_GREEN] || rss_color[RTE_COLOR_YELLOW])
   20284                 :          0 :                 *is_rss = true;
   20285                 :            :         /* "domain_color[C]" is non-zero for each color, default is ALL. */
   20286         [ #  # ]:          0 :         if (!def_green && !def_yellow &&
   20287         [ #  # ]:          0 :             domain_color[RTE_COLOR_GREEN] != domain_color[RTE_COLOR_YELLOW] &&
   20288         [ #  # ]:          0 :             !(action_flags[RTE_COLOR_GREEN] & MLX5_FLOW_ACTION_DROP) &&
   20289         [ #  # ]:          0 :             !(action_flags[RTE_COLOR_YELLOW] & MLX5_FLOW_ACTION_DROP))
   20290                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   20291                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20292                 :            :                                           NULL, "policy domains conflict");
   20293                 :            :         /*
   20294                 :            :          * At least one color policy is listed in the actions, the domains
   20295                 :            :          * to be supported should be the intersection.
   20296                 :            :          */
   20297                 :          0 :         *domain_bitmap = domain_color[RTE_COLOR_GREEN] &
   20298                 :          0 :                          domain_color[RTE_COLOR_YELLOW];
   20299                 :          0 :         return 0;
   20300                 :            : }
   20301                 :            : 
   20302                 :            : static int
   20303                 :          0 : flow_dv_sync_domain(struct rte_eth_dev *dev, uint32_t domains, uint32_t flags)
   20304                 :            : {
   20305                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20306                 :            :         int ret = 0;
   20307                 :            : 
   20308   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_NIC_RX) && priv->sh->rx_domain != NULL) {
   20309                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->rx_domain,
   20310                 :            :                                                 flags);
   20311         [ #  # ]:          0 :                 if (ret != 0)
   20312                 :            :                         return ret;
   20313                 :            :         }
   20314   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_NIC_TX) && priv->sh->tx_domain != NULL) {
   20315                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->tx_domain, flags);
   20316         [ #  # ]:          0 :                 if (ret != 0)
   20317                 :            :                         return ret;
   20318                 :            :         }
   20319   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_FDB) && priv->sh->fdb_domain != NULL) {
   20320                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->fdb_domain, flags);
   20321         [ #  # ]:          0 :                 if (ret != 0)
   20322                 :          0 :                         return ret;
   20323                 :            :         }
   20324                 :            :         return 0;
   20325                 :            : }
   20326                 :            : 
   20327                 :            : /**
   20328                 :            :  * Discover the number of available flow priorities
   20329                 :            :  * by trying to create a flow with the highest priority value
   20330                 :            :  * for each possible number.
   20331                 :            :  *
   20332                 :            :  * @param[in] dev
   20333                 :            :  *   Ethernet device.
   20334                 :            :  * @param[in] vprio
   20335                 :            :  *   List of possible number of available priorities.
   20336                 :            :  * @param[in] vprio_n
   20337                 :            :  *   Size of @p vprio array.
   20338                 :            :  * @return
   20339                 :            :  *   On success, number of available flow priorities.
   20340                 :            :  *   On failure, a negative errno-style code and rte_errno is set.
   20341                 :            :  */
   20342                 :            : static int
   20343                 :          0 : flow_dv_discover_priorities(struct rte_eth_dev *dev,
   20344                 :            :                             const uint16_t *vprio, int vprio_n)
   20345                 :            : {
   20346                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20347                 :          0 :         struct mlx5_indexed_pool *pool = priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW];
   20348                 :            :         struct rte_flow_item_eth eth;
   20349                 :          0 :         struct rte_flow_item item = {
   20350                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   20351                 :            :                 .spec = &eth,
   20352                 :            :                 .mask = &eth,
   20353                 :            :         };
   20354                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   20355                 :            :                 .mask = {
   20356                 :            :                         .size = sizeof(matcher.mask.buf),
   20357                 :            :                 },
   20358                 :            :         };
   20359                 :            :         union mlx5_flow_tbl_key tbl_key;
   20360                 :            :         struct mlx5_flow flow;
   20361                 :            :         void *action;
   20362                 :            :         struct rte_flow_error error;
   20363                 :            :         uint8_t misc_mask;
   20364                 :            :         int i, err, ret = -ENOTSUP;
   20365                 :            : 
   20366                 :            :         /*
   20367                 :            :          * Prepare a flow with a catch-all pattern and a drop action.
   20368                 :            :          * Use drop queue, because shared drop action may be unavailable.
   20369                 :            :          */
   20370                 :          0 :         action = priv->drop_queue.hrxq->action;
   20371         [ #  # ]:          0 :         if (action == NULL) {
   20372                 :          0 :                 DRV_LOG(ERR, "Priority discovery requires a drop action");
   20373                 :          0 :                 rte_errno = ENOTSUP;
   20374                 :          0 :                 return -rte_errno;
   20375                 :            :         }
   20376                 :            :         memset(&flow, 0, sizeof(flow));
   20377                 :          0 :         flow.handle = mlx5_ipool_zmalloc(pool, &flow.handle_idx);
   20378         [ #  # ]:          0 :         if (flow.handle == NULL) {
   20379                 :          0 :                 DRV_LOG(ERR, "Cannot create flow handle");
   20380                 :          0 :                 rte_errno = ENOMEM;
   20381                 :          0 :                 return -rte_errno;
   20382                 :            :         }
   20383                 :          0 :         flow.ingress = true;
   20384                 :          0 :         flow.dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);
   20385                 :          0 :         flow.dv.actions[0] = action;
   20386                 :          0 :         flow.dv.actions_n = 1;
   20387                 :            :         memset(&eth, 0, sizeof(eth));
   20388                 :          0 :         flow_dv_translate_item_eth(matcher.mask.buf, &item,
   20389                 :            :                                    /* inner */ false, /* group */ 0,
   20390                 :            :                                    MLX5_SET_MATCHER_SW_M);
   20391                 :          0 :         flow_dv_translate_item_eth(flow.dv.value.buf, &item,
   20392                 :            :                                    /* inner */ false, /* group */ 0,
   20393                 :            :                                    MLX5_SET_MATCHER_SW_V);
   20394                 :          0 :         matcher.crc = rte_raw_cksum(matcher.mask.buf, matcher.mask.size);
   20395         [ #  # ]:          0 :         for (i = 0; i < vprio_n; i++) {
   20396                 :            :                 /* Configure the next proposed maximum priority. */
   20397                 :          0 :                 matcher.priority = vprio[i] - 1;
   20398                 :            :                 memset(&tbl_key, 0, sizeof(tbl_key));
   20399                 :          0 :                 err = flow_dv_matcher_register(dev, &matcher, &tbl_key, &flow,
   20400                 :            :                                                /* tunnel */ NULL,
   20401                 :            :                                                /* group */ 0,
   20402                 :            :                                                &error);
   20403         [ #  # ]:          0 :                 if (err != 0) {
   20404                 :            :                         /* This action is pure SW and must always succeed. */
   20405                 :          0 :                         DRV_LOG(ERR, "Cannot register matcher");
   20406                 :          0 :                         ret = -rte_errno;
   20407                 :          0 :                         break;
   20408                 :            :                 }
   20409                 :            :                 /* Try to apply the flow to HW. */
   20410         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(flow.handle->dvh.matcher->mask.buf);
   20411                 :            :                 __flow_dv_adjust_buf_size(&flow.dv.value.size, misc_mask);
   20412                 :          0 :                 err = mlx5_flow_os_create_flow
   20413                 :            :                                 (flow.handle->dvh.matcher->matcher_object,
   20414                 :          0 :                                  (void *)&flow.dv.value, flow.dv.actions_n,
   20415                 :            :                                  flow.dv.actions, &flow.handle->drv_flow);
   20416                 :            :                 if (err == 0) {
   20417                 :          0 :                         claim_zero(mlx5_flow_os_destroy_flow
   20418                 :            :                                                 (flow.handle->drv_flow));
   20419                 :          0 :                         flow.handle->drv_flow = NULL;
   20420                 :            :                 }
   20421                 :          0 :                 claim_zero(flow_dv_matcher_release(dev, flow.handle));
   20422         [ #  # ]:          0 :                 if (err != 0)
   20423                 :            :                         break;
   20424                 :          0 :                 ret = vprio[i];
   20425                 :            :         }
   20426                 :          0 :         mlx5_ipool_free(pool, flow.handle_idx);
   20427                 :            :         /* Set rte_errno if no expected priority value matched. */
   20428         [ #  # ]:          0 :         if (ret < 0)
   20429                 :          0 :                 rte_errno = -ret;
   20430                 :            :         return ret;
   20431                 :            : }
   20432                 :            : 
   20433                 :            : const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
   20434                 :            :         .list_create = flow_legacy_list_create,
   20435                 :            :         .list_destroy = flow_legacy_list_destroy,
   20436                 :            :         .validate = flow_dv_validate,
   20437                 :            :         .prepare = flow_dv_prepare,
   20438                 :            :         .translate = flow_dv_translate,
   20439                 :            :         .apply = flow_dv_apply,
   20440                 :            :         .remove = flow_dv_remove,
   20441                 :            :         .destroy = flow_dv_destroy,
   20442                 :            :         .query = flow_dv_query,
   20443                 :            :         .create_mtr_tbls = flow_dv_create_mtr_tbls,
   20444                 :            :         .destroy_mtr_tbls = flow_dv_destroy_mtr_tbls,
   20445                 :            :         .destroy_mtr_drop_tbls = flow_dv_destroy_mtr_drop_tbls,
   20446                 :            :         .create_meter = flow_dv_mtr_alloc,
   20447                 :            :         .free_meter = flow_dv_aso_mtr_release_to_pool,
   20448                 :            :         .validate_mtr_acts = flow_dv_validate_mtr_policy_acts,
   20449                 :            :         .create_mtr_acts = flow_dv_create_mtr_policy_acts,
   20450                 :            :         .destroy_mtr_acts = flow_dv_destroy_mtr_policy_acts,
   20451                 :            :         .create_policy_rules = flow_dv_create_policy_rules,
   20452                 :            :         .destroy_policy_rules = flow_dv_destroy_policy_rules,
   20453                 :            :         .create_def_policy = flow_dv_create_def_policy,
   20454                 :            :         .destroy_def_policy = flow_dv_destroy_def_policy,
   20455                 :            :         .meter_sub_policy_rss_prepare = flow_dv_meter_sub_policy_rss_prepare,
   20456                 :            :         .meter_hierarchy_rule_create = flow_dv_meter_hierarchy_rule_create,
   20457                 :            :         .destroy_sub_policy_with_rxq = flow_dv_destroy_sub_policy_with_rxq,
   20458                 :            :         .counter_alloc = flow_dv_counter_allocate,
   20459                 :            :         .counter_free = flow_dv_counter_free,
   20460                 :            :         .counter_query = flow_dv_counter_query,
   20461                 :            :         .get_aged_flows = flow_dv_get_aged_flows,
   20462                 :            :         .action_validate = flow_dv_action_validate,
   20463                 :            :         .action_create = flow_dv_action_create,
   20464                 :            :         .action_destroy = flow_dv_action_destroy,
   20465                 :            :         .action_update = flow_dv_action_update,
   20466                 :            :         .action_query = flow_dv_action_query,
   20467                 :            :         .sync_domain = flow_dv_sync_domain,
   20468                 :            :         .discover_priorities = flow_dv_discover_priorities,
   20469                 :            :         .item_create = flow_dv_item_create,
   20470                 :            :         .item_release = flow_dv_item_release,
   20471                 :            : };
   20472                 :            : 
   20473                 :            : #endif /* HAVE_IBV_FLOW_DV_SUPPORT */

Generated by: LCOV version 1.14