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 7567 0.0 %
Date: 2025-04-03 19:37:06 Functions: 0 289 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 6072 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                 :            :                         /*
    7929                 :            :                          * explicitly allow inner IPIP match
    7930                 :            :                          */
    7931                 :            :                         if (l3_tunnel_detection == l3_tunnel_outer) {
    7932                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7933                 :            :                                 tunnel = 1;
    7934                 :            :                         }
    7935                 :          0 :                         ret = mlx5_flow_dv_validate_item_ipv4(dev, items,
    7936                 :            :                                                               item_flags,
    7937                 :            :                                                               last_item,
    7938                 :            :                                                               ether_type,
    7939                 :            :                                                               &nic_ipv4_mask,
    7940                 :            :                                                               error);
    7941         [ #  # ]:          0 :                         if (ret < 0)
    7942                 :          0 :                                 return ret;
    7943         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    7944                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    7945         [ #  # ]:          0 :                         if (l3_tunnel_detection == l3_tunnel_outer)
    7946                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7947                 :            :                         break;
    7948                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    7949                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7950                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7951                 :            :                         l3_tunnel_detection =
    7952                 :            :                                 mlx5_flow_tunnel_ip_check(items, next_protocol,
    7953                 :            :                                                           item_flags,
    7954                 :            :                                                           &l3_tunnel_flag);
    7955                 :            :                         /*
    7956                 :            :                          * explicitly allow inner IPIP match
    7957                 :            :                          */
    7958                 :            :                         if (l3_tunnel_detection == l3_tunnel_outer) {
    7959                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7960                 :            :                                 tunnel = 1;
    7961                 :            :                         }
    7962                 :          0 :                         ret = mlx5_flow_validate_item_ipv6(dev, items,
    7963                 :            :                                                            item_flags,
    7964                 :            :                                                            last_item,
    7965                 :            :                                                            ether_type,
    7966                 :            :                                                            &nic_ipv6_mask,
    7967                 :            :                                                            error);
    7968         [ #  # ]:          0 :                         if (ret < 0)
    7969                 :          0 :                                 return ret;
    7970         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    7971                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    7972         [ #  # ]:          0 :                         if (l3_tunnel_detection == l3_tunnel_outer)
    7973                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7974                 :            :                         break;
    7975                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
    7976                 :          0 :                         ret = flow_dv_validate_item_ipv6_frag_ext(dev, items,
    7977                 :            :                                                                   item_flags,
    7978                 :            :                                                                   error);
    7979         [ #  # ]:          0 :                         if (ret < 0)
    7980                 :          0 :                                 return ret;
    7981         [ #  # ]:          0 :                         last_item = tunnel ?
    7982         [ #  # ]:          0 :                                         MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT :
    7983                 :            :                                         MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT;
    7984                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7985                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7986                 :            :                         break;
    7987                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
    7988                 :          0 :                         ret = mlx5_flow_validate_item_tcp
    7989                 :            :                                                 (dev, items, item_flags,
    7990                 :            :                                                  next_protocol,
    7991                 :            :                                                  &nic_tcp_mask,
    7992                 :            :                                                  error);
    7993         [ #  # ]:          0 :                         if (ret < 0)
    7994                 :          0 :                                 return ret;
    7995         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
    7996                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_TCP;
    7997                 :          0 :                         break;
    7998                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    7999                 :          0 :                         ret = mlx5_flow_validate_item_udp(dev, items, item_flags,
    8000                 :            :                                                           next_protocol,
    8001                 :            :                                                           error);
    8002                 :          0 :                         const struct rte_flow_item_udp *spec = items->spec;
    8003                 :          0 :                         const struct rte_flow_item_udp *mask = items->mask;
    8004         [ #  # ]:          0 :                         if (!mask)
    8005                 :            :                                 mask = &rte_flow_item_udp_mask;
    8006         [ #  # ]:          0 :                         if (spec != NULL)
    8007         [ #  # ]:          0 :                                 udp_dport = rte_be_to_cpu_16
    8008                 :            :                                                 (spec->hdr.dst_port &
    8009                 :            :                                                  mask->hdr.dst_port);
    8010         [ #  # ]:          0 :                         if (ret < 0)
    8011                 :          0 :                                 return ret;
    8012         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
    8013                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_UDP;
    8014                 :          0 :                         break;
    8015                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
    8016                 :          0 :                         ret = mlx5_flow_validate_item_gre(dev, items, item_flags,
    8017                 :            :                                                           next_protocol, error);
    8018         [ #  # ]:          0 :                         if (ret < 0)
    8019                 :          0 :                                 return ret;
    8020                 :            :                         gre_item = items;
    8021                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE;
    8022                 :          0 :                         break;
    8023                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
    8024                 :          0 :                         ret = mlx5_flow_validate_item_gre_option(dev, items, item_flags,
    8025                 :            :                                                           attr, gre_item, error);
    8026         [ #  # ]:          0 :                         if (ret < 0)
    8027                 :          0 :                                 return ret;
    8028                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE;
    8029                 :          0 :                         break;
    8030                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    8031                 :          0 :                         ret = mlx5_flow_validate_item_nvgre(dev, items,
    8032                 :            :                                                             item_flags,
    8033                 :            :                                                             next_protocol,
    8034                 :            :                                                             error);
    8035         [ #  # ]:          0 :                         if (ret < 0)
    8036                 :          0 :                                 return ret;
    8037                 :          0 :                         last_item = MLX5_FLOW_LAYER_NVGRE;
    8038                 :          0 :                         break;
    8039                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
    8040                 :          0 :                         ret = mlx5_flow_validate_item_gre_key
    8041                 :            :                                 (dev, items, item_flags, gre_item, error);
    8042         [ #  # ]:          0 :                         if (ret < 0)
    8043                 :          0 :                                 return ret;
    8044                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE_KEY;
    8045                 :          0 :                         break;
    8046                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    8047                 :          0 :                         ret = mlx5_flow_validate_item_vxlan(dev, udp_dport,
    8048                 :            :                                                             items, item_flags,
    8049                 :            :                                                             is_root, error);
    8050         [ #  # ]:          0 :                         if (ret < 0)
    8051                 :          0 :                                 return ret;
    8052                 :          0 :                         last_item = MLX5_FLOW_LAYER_VXLAN;
    8053                 :          0 :                         break;
    8054                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    8055                 :          0 :                         ret = mlx5_flow_validate_item_vxlan_gpe(items,
    8056                 :            :                                                                 item_flags, dev,
    8057                 :            :                                                                 error);
    8058         [ #  # ]:          0 :                         if (ret < 0)
    8059                 :          0 :                                 return ret;
    8060                 :          0 :                         last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
    8061                 :          0 :                         break;
    8062                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
    8063                 :          0 :                         ret = mlx5_flow_validate_item_geneve(items,
    8064                 :            :                                                              item_flags, dev,
    8065                 :            :                                                              error);
    8066         [ #  # ]:          0 :                         if (ret < 0)
    8067                 :          0 :                                 return ret;
    8068                 :            :                         geneve_item = items;
    8069                 :          0 :                         last_item = MLX5_FLOW_LAYER_GENEVE;
    8070                 :          0 :                         break;
    8071                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
    8072                 :          0 :                         ret = mlx5_flow_validate_item_geneve_opt(items,
    8073                 :            :                                                                  last_item,
    8074                 :            :                                                                  geneve_item,
    8075                 :            :                                                                  dev,
    8076                 :            :                                                                  error);
    8077         [ #  # ]:          0 :                         if (ret < 0)
    8078                 :          0 :                                 return ret;
    8079                 :          0 :                         last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
    8080                 :          0 :                         break;
    8081                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MPLS:
    8082                 :          0 :                         ret = mlx5_flow_validate_item_mpls(dev, items,
    8083                 :            :                                                            item_flags,
    8084                 :            :                                                            last_item, error);
    8085         [ #  # ]:          0 :                         if (ret < 0)
    8086                 :          0 :                                 return ret;
    8087                 :          0 :                         last_item = MLX5_FLOW_LAYER_MPLS;
    8088                 :          0 :                         break;
    8089                 :            : 
    8090                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MARK:
    8091                 :          0 :                         ret = flow_dv_validate_item_mark(dev, items, attr,
    8092                 :            :                                                          error);
    8093         [ #  # ]:          0 :                         if (ret < 0)
    8094                 :          0 :                                 return ret;
    8095                 :          0 :                         last_item = MLX5_FLOW_ITEM_MARK;
    8096                 :          0 :                         break;
    8097                 :          0 :                 case RTE_FLOW_ITEM_TYPE_META:
    8098                 :          0 :                         ret = flow_dv_validate_item_meta(dev, items, attr,
    8099                 :            :                                                          error);
    8100         [ #  # ]:          0 :                         if (ret < 0)
    8101                 :          0 :                                 return ret;
    8102                 :          0 :                         last_item = MLX5_FLOW_ITEM_METADATA;
    8103                 :          0 :                         break;
    8104                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP:
    8105                 :          0 :                         ret = mlx5_flow_validate_item_icmp(dev, items, item_flags,
    8106                 :            :                                                            next_protocol,
    8107                 :            :                                                            error);
    8108         [ #  # ]:          0 :                         if (ret < 0)
    8109                 :          0 :                                 return ret;
    8110                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP;
    8111                 :          0 :                         break;
    8112                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6:
    8113                 :          0 :                         ret = mlx5_flow_validate_item_icmp6(dev, items, item_flags,
    8114                 :            :                                                             next_protocol,
    8115                 :            :                                                             error);
    8116         [ #  # ]:          0 :                         if (ret < 0)
    8117                 :          0 :                                 return ret;
    8118                 :            :                         item_ipv6_proto = IPPROTO_ICMPV6;
    8119                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8120                 :          0 :                         break;
    8121                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
    8122                 :            :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
    8123                 :          0 :                         ret = mlx5_flow_validate_item_icmp6_echo(dev, items,
    8124                 :            :                                                                  item_flags,
    8125                 :            :                                                                  next_protocol,
    8126                 :            :                                                                  error);
    8127         [ #  # ]:          0 :                         if (ret < 0)
    8128                 :          0 :                                 return ret;
    8129                 :            :                         item_ipv6_proto = IPPROTO_ICMPV6;
    8130                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8131                 :          0 :                         break;
    8132                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TAG:
    8133                 :          0 :                         ret = flow_dv_validate_item_tag(dev, items, &tag_bitmap,
    8134                 :            :                                                         attr, error);
    8135         [ #  # ]:          0 :                         if (ret < 0)
    8136                 :          0 :                                 return ret;
    8137                 :          0 :                         last_item = MLX5_FLOW_ITEM_TAG;
    8138                 :          0 :                         break;
    8139                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
    8140                 :            :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
    8141                 :          0 :                         last_item = MLX5_FLOW_ITEM_SQ;
    8142                 :          0 :                         break;
    8143                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
    8144                 :          0 :                         mlx5_tag = (const struct mlx5_rte_flow_item_tag *)items->spec;
    8145         [ #  # ]:          0 :                         if (tag_bitmap & (1 << mlx5_tag->id))
    8146                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8147                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    8148                 :            :                                                           items->spec,
    8149                 :            :                                                           "Duplicated tag index");
    8150                 :          0 :                         tag_bitmap |= 1 << mlx5_tag->id;
    8151                 :          0 :                         break;
    8152                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP:
    8153                 :          0 :                         ret = mlx5_flow_dv_validate_item_gtp(dev, items,
    8154                 :            :                                                              item_flags,
    8155                 :            :                                                              error);
    8156         [ #  # ]:          0 :                         if (ret < 0)
    8157                 :          0 :                                 return ret;
    8158                 :            :                         gtp_item = items;
    8159                 :          0 :                         last_item = MLX5_FLOW_LAYER_GTP;
    8160                 :          0 :                         break;
    8161                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
    8162                 :          0 :                         ret = mlx5_flow_dv_validate_item_gtp_psc(dev, items,
    8163                 :            :                                                                  last_item,
    8164                 :            :                                                                  gtp_item,
    8165                 :            :                                                                  is_root, error);
    8166         [ #  # ]:          0 :                         if (ret < 0)
    8167                 :          0 :                                 return ret;
    8168                 :          0 :                         last_item = MLX5_FLOW_LAYER_GTP_PSC;
    8169                 :          0 :                         break;
    8170                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ECPRI:
    8171                 :            :                         /* Capacity will be checked in the translate stage. */
    8172                 :          0 :                         ret = mlx5_flow_validate_item_ecpri(dev, items,
    8173                 :            :                                                             item_flags,
    8174                 :            :                                                             last_item,
    8175                 :            :                                                             ether_type,
    8176                 :            :                                                             &nic_ecpri_mask,
    8177                 :            :                                                             error);
    8178         [ #  # ]:          0 :                         if (ret < 0)
    8179                 :          0 :                                 return ret;
    8180                 :          0 :                         last_item = MLX5_FLOW_LAYER_ECPRI;
    8181                 :          0 :                         break;
    8182                 :          0 :                 case RTE_FLOW_ITEM_TYPE_INTEGRITY:
    8183                 :          0 :                         ret = flow_dv_validate_item_integrity(dev, items,
    8184                 :            :                                                               item_flags,
    8185                 :            :                                                               &last_item,
    8186                 :            :                                                               integrity_items,
    8187                 :            :                                                               error);
    8188         [ #  # ]:          0 :                         if (ret < 0)
    8189                 :          0 :                                 return ret;
    8190                 :            :                         break;
    8191                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
    8192                 :          0 :                         ret = mlx5_flow_dv_validate_item_aso_ct(dev, items,
    8193                 :            :                                                                 &item_flags,
    8194                 :            :                                                                 error);
    8195         [ #  # ]:          0 :                         if (ret < 0)
    8196                 :          0 :                                 return ret;
    8197                 :          0 :                         last_item = MLX5_FLOW_LAYER_ASO_CT;
    8198                 :          0 :                         break;
    8199                 :            :                 case MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL:
    8200                 :            :                         /* tunnel offload item was processed before
    8201                 :            :                          * list it here as a supported type
    8202                 :            :                          */
    8203                 :            :                         break;
    8204                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
    8205                 :          0 :                         ret = flow_dv_validate_item_flex(dev, items, item_flags,
    8206                 :            :                                                          &last_item,
    8207                 :            :                                                          tunnel != 0, error);
    8208         [ #  # ]:          0 :                         if (ret < 0)
    8209                 :          0 :                                 return ret;
    8210                 :            :                         /* Reset for next proto, it is unknown. */
    8211                 :            :                         next_protocol = 0xff;
    8212                 :            :                         break;
    8213                 :          0 :                 case RTE_FLOW_ITEM_TYPE_METER_COLOR:
    8214                 :          0 :                         ret = flow_dv_validate_item_meter_color(dev, items,
    8215                 :            :                                                                 attr, error);
    8216         [ #  # ]:          0 :                         if (ret < 0)
    8217                 :          0 :                                 return ret;
    8218                 :          0 :                         last_item = MLX5_FLOW_ITEM_METER_COLOR;
    8219                 :          0 :                         break;
    8220                 :          0 :                 case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
    8221                 :          0 :                         ret = flow_dv_validate_item_aggr_affinity(dev, items,
    8222                 :            :                                                                   attr, error);
    8223         [ #  # ]:          0 :                         if (ret < 0)
    8224                 :          0 :                                 return ret;
    8225                 :          0 :                         last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
    8226                 :          0 :                         break;
    8227                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IB_BTH:
    8228                 :          0 :                         ret = mlx5_flow_validate_item_ib_bth(dev, udp_dport,
    8229                 :            :                                                             items, is_root, error);
    8230         [ #  # ]:          0 :                         if (ret < 0)
    8231                 :          0 :                                 return ret;
    8232                 :            : 
    8233                 :          0 :                         last_item = MLX5_FLOW_ITEM_IB_BTH;
    8234                 :          0 :                         break;
    8235                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NSH:
    8236                 :          0 :                         ret = mlx5_flow_validate_item_nsh(dev, items, error);
    8237         [ #  # ]:          0 :                         if (ret < 0)
    8238                 :          0 :                                 return ret;
    8239                 :          0 :                         last_item = MLX5_FLOW_ITEM_NSH;
    8240                 :          0 :                         break;
    8241                 :          0 :                 default:
    8242                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8243                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    8244                 :            :                                                   NULL, "item not supported");
    8245                 :            :                 }
    8246                 :          0 :                 item_flags |= last_item;
    8247                 :            :         }
    8248         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
    8249                 :          0 :                 ret = flow_dv_validate_item_integrity_post(integrity_items,
    8250                 :            :                                                            item_flags, error);
    8251         [ #  # ]:          0 :                 if (ret)
    8252                 :            :                         return ret;
    8253                 :            :         }
    8254         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    8255                 :          0 :                 int type = actions->type;
    8256                 :            : 
    8257                 :            :                 if (!mlx5_flow_os_action_supported(type))
    8258                 :            :                         return rte_flow_error_set(error, ENOTSUP,
    8259                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8260                 :            :                                                   actions,
    8261                 :            :                                                   "action not supported");
    8262         [ #  # ]:          0 :                 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
    8263                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8264                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8265                 :            :                                                   actions, "too many actions");
    8266         [ #  # ]:          0 :                 if (action_flags &
    8267                 :            :                         MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
    8268                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8269                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8270                 :            :                                 NULL, "meter action with policy "
    8271                 :            :                                 "must be the last action");
    8272   [ #  #  #  #  :          0 :                 switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    8273                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    8274                 :            :                         break;
    8275                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
    8276                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    8277                 :          0 :                         ret = flow_dv_validate_action_port_id(dev,
    8278                 :            :                                                               action_flags,
    8279                 :            :                                                               actions,
    8280                 :            :                                                               attr,
    8281                 :            :                                                               error);
    8282         [ #  # ]:          0 :                         if (ret)
    8283                 :          0 :                                 return ret;
    8284         [ #  # ]:          0 :                         if (type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
    8285                 :          0 :                                 port = (const struct rte_flow_action_port_id *)
    8286                 :            :                                         actions->conf;
    8287         [ #  # ]:          0 :                                 port_id = port->original ? dev->data->port_id : port->id;
    8288                 :            :                         } else {
    8289                 :          0 :                                 port_id = ((const struct rte_flow_action_ethdev *)
    8290                 :          0 :                                         actions->conf)->port_id;
    8291                 :            :                         }
    8292                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
    8293                 :          0 :                         ++actions_n;
    8294                 :          0 :                         break;
    8295                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    8296                 :          0 :                         ret = flow_dv_validate_action_flag(dev, action_flags,
    8297                 :            :                                                            attr, error);
    8298         [ #  # ]:          0 :                         if (ret < 0)
    8299                 :          0 :                                 return ret;
    8300         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    8301                 :            :                                 /* Count all modify-header actions as one. */
    8302         [ #  # ]:          0 :                                 if (!(action_flags &
    8303                 :            :                                       MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8304                 :          0 :                                         ++actions_n;
    8305                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_FLAG |
    8306                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    8307         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8308                 :            :                                         modify_after_mirror = 1;
    8309                 :            : 
    8310                 :            :                         } else {
    8311                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_FLAG;
    8312                 :          0 :                                 ++actions_n;
    8313                 :            :                         }
    8314                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_MARK;
    8315                 :          0 :                         break;
    8316                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    8317                 :          0 :                         ret = flow_dv_validate_action_mark(dev, actions,
    8318                 :            :                                                            action_flags,
    8319                 :            :                                                            attr, error);
    8320         [ #  # ]:          0 :                         if (ret < 0)
    8321                 :          0 :                                 return ret;
    8322         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    8323                 :            :                                 /* Count all modify-header actions as one. */
    8324         [ #  # ]:          0 :                                 if (!(action_flags &
    8325                 :            :                                       MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8326                 :          0 :                                         ++actions_n;
    8327                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK |
    8328                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    8329         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8330                 :            :                                         modify_after_mirror = 1;
    8331                 :            :                         } else {
    8332                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK;
    8333                 :          0 :                                 ++actions_n;
    8334                 :            :                         }
    8335                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_MARK;
    8336                 :          0 :                         break;
    8337                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_META:
    8338         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    8339                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8340                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8341                 :            :                                                   actions,
    8342                 :            :                                                   "action not supported");
    8343                 :          0 :                         ret = flow_dv_validate_action_set_meta(dev, actions,
    8344                 :            :                                                                action_flags,
    8345                 :            :                                                                attr, error);
    8346         [ #  # ]:          0 :                         if (ret < 0)
    8347                 :          0 :                                 return ret;
    8348                 :            :                         /* Count all modify-header actions as one action. */
    8349         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8350                 :          0 :                                 ++actions_n;
    8351         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8352                 :            :                                 modify_after_mirror = 1;
    8353                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_META;
    8354                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_META;
    8355                 :          0 :                         break;
    8356                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
    8357                 :          0 :                         ret = flow_dv_validate_action_set_tag(dev, actions,
    8358                 :            :                                                               action_flags,
    8359                 :            :                                                               attr, error);
    8360         [ #  # ]:          0 :                         if (ret < 0)
    8361                 :          0 :                                 return ret;
    8362                 :            :                         /* Count all modify-header actions as one action. */
    8363         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8364                 :          0 :                                 ++actions_n;
    8365         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8366                 :            :                                 modify_after_mirror = 1;
    8367                 :          0 :                         tag_id = ((const struct rte_flow_action_set_tag *)
    8368                 :          0 :                                   actions->conf)->index;
    8369                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
    8370                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8371                 :          0 :                         break;
    8372                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
    8373                 :          0 :                         ret = mlx5_flow_validate_action_drop(dev, is_root,
    8374                 :            :                                                              attr, error);
    8375         [ #  # ]:          0 :                         if (ret < 0)
    8376                 :          0 :                                 return ret;
    8377                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
    8378                 :          0 :                         ++actions_n;
    8379                 :          0 :                         break;
    8380                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    8381                 :          0 :                         ret = mlx5_flow_validate_action_queue(actions,
    8382                 :            :                                                               action_flags, dev,
    8383                 :            :                                                               attr, error);
    8384         [ #  # ]:          0 :                         if (ret < 0)
    8385                 :          0 :                                 return ret;
    8386                 :          0 :                         queue_index = ((const struct rte_flow_action_queue *)
    8387                 :          0 :                                                         (actions->conf))->index;
    8388                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
    8389                 :          0 :                         ++actions_n;
    8390                 :          0 :                         break;
    8391                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    8392                 :          0 :                         rss = actions->conf;
    8393                 :          0 :                         ret = mlx5_flow_validate_action_rss(actions,
    8394                 :            :                                                             action_flags, dev,
    8395                 :            :                                                             attr, item_flags,
    8396                 :            :                                                             error);
    8397         [ #  # ]:          0 :                         if (ret < 0)
    8398                 :          0 :                                 return ret;
    8399         [ #  # ]:          0 :                         if (rss && sample_rss &&
    8400         [ #  # ]:          0 :                             (sample_rss->level != rss->level ||
    8401         [ #  # ]:          0 :                             sample_rss->types != rss->types))
    8402                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8403                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8404                 :            :                                         NULL,
    8405                 :            :                                         "Can't use the different RSS types "
    8406                 :            :                                         "or level in the same flow");
    8407   [ #  #  #  # ]:          0 :                         if (rss != NULL && rss->queue_num)
    8408                 :          0 :                                 queue_index = rss->queue[0];
    8409                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
    8410                 :          0 :                         ++actions_n;
    8411                 :          0 :                         break;
    8412                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
    8413                 :            :                         ret =
    8414                 :          0 :                         mlx5_flow_validate_action_default_miss(action_flags,
    8415                 :            :                                         attr, error);
    8416         [ #  # ]:          0 :                         if (ret < 0)
    8417                 :          0 :                                 return ret;
    8418                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
    8419                 :          0 :                         ++actions_n;
    8420                 :          0 :                         break;
    8421                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
    8422                 :            :                         shared_count = true;
    8423                 :            :                         /* fall-through. */
    8424                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    8425                 :          0 :                         ret = flow_dv_validate_action_count(dev, shared_count,
    8426                 :            :                                                             action_flags,
    8427                 :            :                                                             is_root, error);
    8428         [ #  # ]:          0 :                         if (ret < 0)
    8429                 :          0 :                                 return ret;
    8430                 :          0 :                         count = actions->conf;
    8431                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
    8432                 :          0 :                         ++actions_n;
    8433                 :          0 :                         break;
    8434                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    8435         [ #  # ]:          0 :                         if (flow_dv_validate_action_pop_vlan(dev,
    8436                 :            :                                                              action_flags,
    8437                 :            :                                                              actions,
    8438                 :            :                                                              item_flags, attr,
    8439                 :            :                                                              error))
    8440                 :          0 :                                 return -rte_errno;
    8441         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8442                 :            :                                 modify_after_mirror = 1;
    8443                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
    8444                 :          0 :                         ++actions_n;
    8445                 :          0 :                         break;
    8446                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    8447                 :          0 :                         ret = flow_dv_validate_action_push_vlan(dev,
    8448                 :            :                                                                 action_flags,
    8449                 :            :                                                                 vlan_m,
    8450                 :            :                                                                 actions, attr,
    8451                 :            :                                                                 error);
    8452         [ #  # ]:          0 :                         if (ret < 0)
    8453                 :          0 :                                 return ret;
    8454         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8455                 :            :                                 modify_after_mirror = 1;
    8456                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
    8457                 :          0 :                         ++actions_n;
    8458                 :          0 :                         break;
    8459                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    8460                 :          0 :                         ret = flow_dv_validate_action_set_vlan_pcp
    8461                 :            :                                                 (action_flags, actions, error);
    8462         [ #  # ]:          0 :                         if (ret < 0)
    8463                 :          0 :                                 return ret;
    8464         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8465                 :            :                                 modify_after_mirror = 1;
    8466                 :            :                         /* Count PCP with push_vlan command. */
    8467                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;
    8468                 :          0 :                         break;
    8469                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    8470                 :          0 :                         ret = flow_dv_validate_action_set_vlan_vid
    8471                 :            :                                                 (item_flags, action_flags,
    8472                 :            :                                                  actions, error);
    8473         [ #  # ]:          0 :                         if (ret < 0)
    8474                 :          0 :                                 return ret;
    8475         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8476                 :            :                                 modify_after_mirror = 1;
    8477                 :            :                         /* Count VID with push_vlan command. */
    8478                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
    8479                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_VID;
    8480                 :          0 :                         break;
    8481                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    8482                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    8483                 :          0 :                         ret = mlx5_flow_dv_validate_action_l2_encap(dev,
    8484                 :            :                                                                     action_flags,
    8485                 :            :                                                                     actions,
    8486                 :            :                                                                     attr,
    8487                 :            :                                                                     error);
    8488         [ #  # ]:          0 :                         if (ret < 0)
    8489                 :          0 :                                 return ret;
    8490                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
    8491                 :          0 :                         ++actions_n;
    8492                 :          0 :                         break;
    8493                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    8494                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    8495                 :          0 :                         ret = mlx5_flow_dv_validate_action_decap(dev,
    8496                 :            :                                                                  action_flags,
    8497                 :            :                                                                  actions,
    8498                 :            :                                                                  item_flags,
    8499                 :            :                                                                  attr, error);
    8500         [ #  # ]:          0 :                         if (ret < 0)
    8501                 :          0 :                                 return ret;
    8502         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8503                 :            :                                 modify_after_mirror = 1;
    8504                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
    8505                 :          0 :                         ++actions_n;
    8506                 :          0 :                         break;
    8507                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    8508                 :          0 :                         ret = mlx5_flow_dv_validate_action_raw_encap_decap
    8509                 :          0 :                                 (dev, NULL, actions->conf, attr, &action_flags,
    8510                 :            :                                  &actions_n, actions, item_flags, error);
    8511         [ #  # ]:          0 :                         if (ret < 0)
    8512                 :          0 :                                 return ret;
    8513                 :            :                         break;
    8514                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    8515                 :          0 :                         decap = actions->conf;
    8516         [ #  # ]:          0 :                         while ((++actions)->type == RTE_FLOW_ACTION_TYPE_VOID)
    8517                 :            :                                 ;
    8518         [ #  # ]:          0 :                         if (actions->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    8519                 :            :                                 encap = NULL;
    8520                 :            :                                 actions--;
    8521                 :            :                         } else {
    8522                 :          0 :                                 encap = actions->conf;
    8523                 :            :                         }
    8524         [ #  # ]:          0 :                         ret = mlx5_flow_dv_validate_action_raw_encap_decap
    8525                 :            :                                 (dev,
    8526                 :            :                                  decap ? decap : &empty_decap, encap,
    8527                 :            :                                  attr, &action_flags, &actions_n,
    8528                 :            :                                  actions, item_flags, error);
    8529         [ #  # ]:          0 :                         if (ret < 0)
    8530                 :          0 :                                 return ret;
    8531         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) &&
    8532                 :            :                             (action_flags & MLX5_FLOW_ACTION_DECAP))
    8533                 :            :                                 modify_after_mirror = 1;
    8534                 :            :                         break;
    8535                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
    8536                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    8537                 :          0 :                         ret = flow_dv_validate_action_modify_mac(action_flags,
    8538                 :            :                                                                  actions,
    8539                 :            :                                                                  item_flags,
    8540                 :            :                                                                  error);
    8541         [ #  # ]:          0 :                         if (ret < 0)
    8542                 :          0 :                                 return ret;
    8543                 :            :                         /* Count all modify-header actions as one action. */
    8544         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8545                 :          0 :                                 ++actions_n;
    8546                 :          0 :                         action_flags |= actions->type ==
    8547                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
    8548         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_MAC_SRC :
    8549                 :            :                                                 MLX5_FLOW_ACTION_SET_MAC_DST;
    8550         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8551                 :            :                                 modify_after_mirror = 1;
    8552                 :            :                         /*
    8553                 :            :                          * Even if the source and destination MAC addresses have
    8554                 :            :                          * overlap in the header with 4B alignment, the convert
    8555                 :            :                          * function will handle them separately and 4 SW actions
    8556                 :            :                          * will be created. And 2 actions will be added each
    8557                 :            :                          * time no matter how many bytes of address will be set.
    8558                 :            :                          */
    8559                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_MAC;
    8560                 :          0 :                         break;
    8561                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
    8562                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
    8563                 :          0 :                         ret = flow_dv_validate_action_modify_ipv4(action_flags,
    8564                 :            :                                                                   actions,
    8565                 :            :                                                                   item_flags,
    8566                 :            :                                                                   error);
    8567         [ #  # ]:          0 :                         if (ret < 0)
    8568                 :          0 :                                 return ret;
    8569                 :            :                         /* Count all modify-header actions as one action. */
    8570         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8571                 :          0 :                                 ++actions_n;
    8572         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8573                 :            :                                 modify_after_mirror = 1;
    8574                 :          0 :                         action_flags |= actions->type ==
    8575                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
    8576         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_IPV4_SRC :
    8577                 :            :                                                 MLX5_FLOW_ACTION_SET_IPV4_DST;
    8578                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_IPV4;
    8579                 :          0 :                         break;
    8580                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
    8581                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
    8582                 :          0 :                         ret = flow_dv_validate_action_modify_ipv6(action_flags,
    8583                 :            :                                                                   actions,
    8584                 :            :                                                                   item_flags,
    8585                 :            :                                                                   error);
    8586         [ #  # ]:          0 :                         if (ret < 0)
    8587                 :          0 :                                 return ret;
    8588         [ #  # ]:          0 :                         if (item_ipv6_proto == IPPROTO_ICMPV6)
    8589                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8590                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8591                 :            :                                         actions,
    8592                 :            :                                         "Can't change header "
    8593                 :            :                                         "with ICMPv6 proto");
    8594                 :            :                         /* Count all modify-header actions as one action. */
    8595         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8596                 :          0 :                                 ++actions_n;
    8597         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8598                 :            :                                 modify_after_mirror = 1;
    8599                 :          0 :                         action_flags |= actions->type ==
    8600                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
    8601         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_IPV6_SRC :
    8602                 :            :                                                 MLX5_FLOW_ACTION_SET_IPV6_DST;
    8603                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_IPV6;
    8604                 :          0 :                         break;
    8605                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
    8606                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    8607                 :          0 :                         ret = flow_dv_validate_action_modify_tp(action_flags,
    8608                 :            :                                                                 actions,
    8609                 :            :                                                                 item_flags,
    8610                 :            :                                                                 error);
    8611         [ #  # ]:          0 :                         if (ret < 0)
    8612                 :          0 :                                 return ret;
    8613                 :            :                         /* Count all modify-header actions as one action. */
    8614         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8615                 :          0 :                                 ++actions_n;
    8616         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8617                 :            :                                 modify_after_mirror = 1;
    8618                 :          0 :                         action_flags |= actions->type ==
    8619                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
    8620         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_TP_SRC :
    8621                 :            :                                                 MLX5_FLOW_ACTION_SET_TP_DST;
    8622                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_PORT;
    8623                 :          0 :                         break;
    8624                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
    8625                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
    8626                 :          0 :                         ret = flow_dv_validate_action_modify_ttl(action_flags,
    8627                 :            :                                                                  actions,
    8628                 :            :                                                                  item_flags,
    8629                 :            :                                                                  error);
    8630         [ #  # ]:          0 :                         if (ret < 0)
    8631                 :          0 :                                 return ret;
    8632                 :            :                         /* Count all modify-header actions as one action. */
    8633         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8634                 :          0 :                                 ++actions_n;
    8635         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8636                 :            :                                 modify_after_mirror = 1;
    8637                 :          0 :                         action_flags |= actions->type ==
    8638                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TTL ?
    8639         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_TTL :
    8640                 :            :                                                 MLX5_FLOW_ACTION_DEC_TTL;
    8641                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TTL;
    8642                 :          0 :                         break;
    8643                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    8644                 :          0 :                         ret = flow_dv_validate_action_jump(dev, tunnel, actions,
    8645                 :            :                                                            action_flags,
    8646                 :            :                                                            attr, external,
    8647                 :            :                                                            error);
    8648         [ #  # ]:          0 :                         if (ret)
    8649                 :          0 :                                 return ret;
    8650                 :          0 :                         ++actions_n;
    8651                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
    8652                 :          0 :                         break;
    8653                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
    8654                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
    8655                 :          0 :                         ret = flow_dv_validate_action_modify_tcp_seq
    8656                 :            :                                                                 (action_flags,
    8657                 :            :                                                                  actions,
    8658                 :            :                                                                  item_flags,
    8659                 :            :                                                                  error);
    8660         [ #  # ]:          0 :                         if (ret < 0)
    8661                 :          0 :                                 return ret;
    8662                 :            :                         /* Count all modify-header actions as one action. */
    8663         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8664                 :          0 :                                 ++actions_n;
    8665         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8666                 :            :                                 modify_after_mirror = 1;
    8667                 :          0 :                         action_flags |= actions->type ==
    8668                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
    8669         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_INC_TCP_SEQ :
    8670                 :            :                                                 MLX5_FLOW_ACTION_DEC_TCP_SEQ;
    8671                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TCPSEQ;
    8672                 :          0 :                         break;
    8673                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
    8674                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
    8675                 :          0 :                         ret = flow_dv_validate_action_modify_tcp_ack
    8676                 :            :                                                                 (action_flags,
    8677                 :            :                                                                  actions,
    8678                 :            :                                                                  item_flags,
    8679                 :            :                                                                  error);
    8680         [ #  # ]:          0 :                         if (ret < 0)
    8681                 :          0 :                                 return ret;
    8682                 :            :                         /* Count all modify-header actions as one action. */
    8683         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8684                 :          0 :                                 ++actions_n;
    8685         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8686                 :            :                                 modify_after_mirror = 1;
    8687                 :          0 :                         action_flags |= actions->type ==
    8688                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
    8689         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_INC_TCP_ACK :
    8690                 :            :                                                 MLX5_FLOW_ACTION_DEC_TCP_ACK;
    8691                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TCPACK;
    8692                 :          0 :                         break;
    8693                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
    8694                 :            :                         break;
    8695                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
    8696                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
    8697                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8698                 :          0 :                         break;
    8699                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    8700         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    8701                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8702                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8703                 :            :                                                   actions,
    8704                 :            :                                                   "action not supported");
    8705                 :          0 :                         ret = mlx5_flow_validate_action_meter(dev,
    8706                 :            :                                                               action_flags,
    8707                 :            :                                                               item_flags,
    8708                 :            :                                                               actions, attr,
    8709                 :            :                                                               port_id_item,
    8710                 :            :                                                               &def_policy,
    8711                 :            :                                                               error);
    8712         [ #  # ]:          0 :                         if (ret < 0)
    8713                 :          0 :                                 return ret;
    8714                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
    8715         [ #  # ]:          0 :                         if (!def_policy)
    8716                 :          0 :                                 action_flags |=
    8717                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
    8718                 :          0 :                         ++actions_n;
    8719                 :            :                         /* Meter action will add one more TAG action. */
    8720                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8721                 :          0 :                         break;
    8722                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
    8723         [ #  # ]:          0 :                         if (is_root)
    8724                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8725                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8726                 :            :                                                                            NULL,
    8727                 :            :                           "Shared ASO age action is not supported for group 0");
    8728         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_AGE)
    8729                 :          0 :                                 return rte_flow_error_set
    8730                 :            :                                                   (error, EINVAL,
    8731                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION,
    8732                 :            :                                                    NULL,
    8733                 :            :                                                    "duplicate age actions set");
    8734         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8735                 :            :                                 aso_after_sample = 1;
    8736                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    8737                 :          0 :                         ++actions_n;
    8738                 :          0 :                         break;
    8739                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
    8740                 :          0 :                         non_shared_age = actions->conf;
    8741                 :          0 :                         ret = flow_dv_validate_action_age(action_flags,
    8742                 :            :                                                           actions, dev,
    8743                 :            :                                                           error);
    8744         [ #  # ]:          0 :                         if (ret < 0)
    8745                 :          0 :                                 return ret;
    8746                 :            :                         /*
    8747                 :            :                          * Validate the regular AGE action (using counter)
    8748                 :            :                          * mutual exclusion with indirect counter actions.
    8749                 :            :                          */
    8750         [ #  # ]:          0 :                         if (!flow_hit_aso_supported(priv, is_root)) {
    8751         [ #  # ]:          0 :                                 if (shared_count)
    8752                 :          0 :                                         return rte_flow_error_set
    8753                 :            :                                                 (error, EINVAL,
    8754                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8755                 :            :                                                 NULL,
    8756                 :            :                                                 "old age and indirect count combination is not supported");
    8757         [ #  # ]:          0 :                                 if (sample_count)
    8758                 :          0 :                                         return rte_flow_error_set
    8759                 :            :                                                 (error, EINVAL,
    8760                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8761                 :            :                                                 NULL,
    8762                 :            :                                                 "old age action and count must be in the same sub flow");
    8763                 :            :                         } else {
    8764         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8765                 :            :                                         aso_after_sample = 1;
    8766                 :            :                         }
    8767                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    8768                 :          0 :                         ++actions_n;
    8769                 :          0 :                         break;
    8770                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
    8771                 :          0 :                         ret = flow_dv_validate_action_modify_ipv4_dscp
    8772                 :            :                                                          (action_flags,
    8773                 :            :                                                           actions,
    8774                 :            :                                                           item_flags,
    8775                 :            :                                                           error);
    8776         [ #  # ]:          0 :                         if (ret < 0)
    8777                 :          0 :                                 return ret;
    8778                 :            :                         /* Count all modify-header actions as one action. */
    8779         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8780                 :          0 :                                 ++actions_n;
    8781         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8782                 :            :                                 modify_after_mirror = 1;
    8783                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
    8784                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_DSCP;
    8785                 :          0 :                         break;
    8786                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
    8787                 :          0 :                         ret = flow_dv_validate_action_modify_ipv6_dscp
    8788                 :            :                                                                 (action_flags,
    8789                 :            :                                                                  actions,
    8790                 :            :                                                                  item_flags,
    8791                 :            :                                                                  error);
    8792         [ #  # ]:          0 :                         if (ret < 0)
    8793                 :          0 :                                 return ret;
    8794                 :            :                         /* Count all modify-header actions as one action. */
    8795         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8796                 :          0 :                                 ++actions_n;
    8797         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8798                 :            :                                 modify_after_mirror = 1;
    8799                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
    8800                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_DSCP;
    8801                 :          0 :                         break;
    8802                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
    8803                 :          0 :                         ret = flow_dv_validate_action_sample(&action_flags,
    8804                 :            :                                                              &sub_action_flags,
    8805                 :            :                                                              actions, dev,
    8806                 :            :                                                              attr, item_flags,
    8807                 :            :                                                              rss, &sample_rss,
    8808                 :            :                                                              &sample_count,
    8809                 :            :                                                              &fdb_mirror,
    8810                 :            :                                                              &sample_port_id,
    8811                 :            :                                                              is_root,
    8812                 :            :                                                              error);
    8813         [ #  # ]:          0 :                         if (ret < 0)
    8814                 :          0 :                                 return ret;
    8815   [ #  #  #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) &&
    8816                 :          0 :                             tag_id == 0 &&
    8817         [ #  # ]:          0 :                             priv->sh->registers.aso_reg == REG_NON)
    8818                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8819                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8820                 :            :                                         "sample after tag action causes metadata tag index 0 corruption");
    8821                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SAMPLE;
    8822                 :          0 :                         ++actions_n;
    8823                 :          0 :                         break;
    8824                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    8825                 :          0 :                         ret = flow_dv_validate_action_modify_field(dev,
    8826                 :            :                                                                    action_flags,
    8827                 :            :                                                                    actions,
    8828                 :            :                                                                    attr,
    8829                 :            :                                                                    is_root,
    8830                 :            :                                                                    error);
    8831         [ #  # ]:          0 :                         if (ret < 0)
    8832                 :          0 :                                 return ret;
    8833         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8834                 :            :                                 modify_after_mirror = 1;
    8835                 :            :                         /* Count all modify-header actions as one action. */
    8836         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8837                 :          0 :                                 ++actions_n;
    8838                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
    8839                 :          0 :                         rw_act_num += ret;
    8840                 :          0 :                         break;
    8841                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    8842                 :          0 :                         ret = mlx5_flow_dv_validate_action_aso_ct(dev,
    8843                 :            :                                                                   action_flags,
    8844                 :            :                                                                   item_flags,
    8845                 :            :                                                                   is_root,
    8846                 :            :                                                                   error);
    8847         [ #  # ]:          0 :                         if (ret < 0)
    8848                 :          0 :                                 return ret;
    8849         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8850                 :            :                                 aso_after_sample = 1;
    8851                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
    8852                 :          0 :                         break;
    8853                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET:
    8854                 :            :                         /* tunnel offload action was processed before
    8855                 :            :                          * list it here as a supported type
    8856                 :            :                          */
    8857                 :            :                         break;
    8858                 :            : #ifdef HAVE_MLX5DV_DR_ACTION_CREATE_DEST_ROOT_TABLE
    8859                 :            :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
    8860                 :            :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
    8861                 :            :                         ++actions_n;
    8862                 :            :                         break;
    8863                 :            : #endif
    8864                 :          0 :                 default:
    8865                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8866                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8867                 :            :                                                   actions,
    8868                 :            :                                                   "action not supported");
    8869                 :            :                 }
    8870                 :            :         }
    8871                 :            :         /*
    8872                 :            :          * Validate actions in flow rules
    8873                 :            :          * - Explicit decap action is prohibited by the tunnel offload API.
    8874                 :            :          * - Drop action in tunnel steer rule is prohibited by the API.
    8875                 :            :          * - Application cannot use MARK action because it's value can mask
    8876                 :            :          *   tunnel default miss notification.
    8877                 :            :          * - JUMP in tunnel match rule has no support in current PMD
    8878                 :            :          *   implementation.
    8879                 :            :          * - TAG & META are reserved for future uses.
    8880                 :            :          */
    8881         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_TUNNEL_SET) {
    8882                 :            :                 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_DECAP    |
    8883                 :            :                                             MLX5_FLOW_ACTION_MARK     |
    8884                 :            :                                             MLX5_FLOW_ACTION_SET_TAG  |
    8885                 :            :                                             MLX5_FLOW_ACTION_SET_META |
    8886                 :            :                                             MLX5_FLOW_ACTION_DROP;
    8887                 :            : 
    8888         [ #  # ]:          0 :                 if (action_flags & bad_actions_mask)
    8889                 :          0 :                         return rte_flow_error_set
    8890                 :            :                                         (error, EINVAL,
    8891                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8892                 :            :                                         "Invalid RTE action in tunnel "
    8893                 :            :                                         "set decap rule");
    8894         [ #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_ACTION_JUMP))
    8895                 :          0 :                         return rte_flow_error_set
    8896                 :            :                                         (error, EINVAL,
    8897                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8898                 :            :                                         "tunnel set decap rule must terminate "
    8899                 :            :                                         "with JUMP");
    8900         [ #  # ]:          0 :                 if (attr->egress)
    8901                 :          0 :                         return rte_flow_error_set
    8902                 :            :                                         (error, EINVAL,
    8903                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8904                 :            :                                         "tunnel flows for ingress and transfer traffic only");
    8905                 :            :         }
    8906         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_TUNNEL_MATCH) {
    8907                 :            :                 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_JUMP    |
    8908                 :            :                                             MLX5_FLOW_ACTION_MARK    |
    8909                 :            :                                             MLX5_FLOW_ACTION_SET_TAG |
    8910                 :            :                                             MLX5_FLOW_ACTION_SET_META;
    8911                 :            : 
    8912         [ #  # ]:          0 :                 if (action_flags & bad_actions_mask)
    8913                 :          0 :                         return rte_flow_error_set
    8914                 :            :                                         (error, EINVAL,
    8915                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8916                 :            :                                         "Invalid RTE action in tunnel "
    8917                 :            :                                         "set match rule");
    8918                 :            :         }
    8919                 :            :         /*
    8920                 :            :          * Validate the drop action mutual exclusion with other actions.
    8921                 :            :          * Drop action is mutually-exclusive with any other action, except for
    8922                 :            :          * Count/Sample/Age actions.
    8923                 :            :          * Drop action compatibility with tunnel offload was already validated.
    8924                 :            :          */
    8925         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_MATCH |
    8926                 :            :                             MLX5_FLOW_ACTION_TUNNEL_MATCH));
    8927         [ #  # ]:          0 :         else if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
    8928         [ #  # ]:          0 :             (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_DROP_INCLUSIVE_ACTIONS)))
    8929                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    8930                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8931                 :            :                                           "Drop action is mutually-exclusive "
    8932                 :            :                                           "with any other action, except for "
    8933                 :            :                                           "Count/Sample/Age action");
    8934                 :            :         /* Eswitch has few restrictions on using items and actions */
    8935         [ #  # ]:          0 :         if (attr->transfer) {
    8936         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev) &&
    8937         [ #  # ]:          0 :                     action_flags & MLX5_FLOW_ACTION_FLAG)
    8938                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8939                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8940                 :            :                                                   NULL,
    8941                 :            :                                                   "unsupported action FLAG");
    8942         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev) &&
    8943         [ #  # ]:          0 :                     action_flags & MLX5_FLOW_ACTION_MARK)
    8944                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8945                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8946                 :            :                                                   NULL,
    8947                 :            :                                                   "unsupported action MARK");
    8948         [ #  # ]:          0 :                 if (!priv->jump_fdb_rx_en) {
    8949         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_QUEUE)
    8950                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8951                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    8952                 :            :                                                           NULL,
    8953                 :            :                                                           "unsupported action QUEUE");
    8954         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_RSS)
    8955                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8956                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    8957                 :            :                                                           NULL,
    8958                 :            :                                                           "unsupported action RSS");
    8959         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    8960                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8961                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    8962                 :            :                                                           actions,
    8963                 :            :                                                           "no fate action is found");
    8964                 :            :                 }
    8965                 :            :         } else {
    8966   [ #  #  #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_FATE_ACTIONS) && attr->ingress)
    8967                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8968                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8969                 :            :                                                   actions,
    8970                 :            :                                                   "no fate action is found");
    8971                 :            :         }
    8972                 :            :         /*
    8973                 :            :          * Continue validation for Xcap and VLAN actions.
    8974                 :            :          * If hairpin is working in explicit TX rule mode, there is no actions
    8975                 :            :          * splitting and the validation of hairpin ingress flow should be the
    8976                 :            :          * same as other standard flows.
    8977                 :            :          */
    8978         [ #  # ]:          0 :         if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS |
    8979         [ #  # ]:          0 :                              MLX5_FLOW_VLAN_ACTIONS)) &&
    8980   [ #  #  #  # ]:          0 :             (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index) ||
    8981                 :          0 :              ((conf = mlx5_rxq_get_hairpin_conf(dev, queue_index)) != NULL &&
    8982         [ #  # ]:          0 :              conf->tx_explicit != 0))) {
    8983         [ #  # ]:          0 :                 if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
    8984                 :            :                     MLX5_FLOW_XCAP_ACTIONS)
    8985                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8986                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8987                 :            :                                                   NULL, "encap and decap "
    8988                 :            :                                                   "combination aren't supported");
    8989                 :            :                 /* Push VLAN is not supported in ingress except for NICs newer than CX5. */
    8990         [ #  # ]:          0 :                 if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) {
    8991                 :          0 :                         struct mlx5_dev_ctx_shared *sh = priv->sh;
    8992                 :            :                         bool direction_error = false;
    8993                 :            : 
    8994         [ #  # ]:          0 :                         if (attr->transfer) {
    8995         [ #  # ]:          0 :                                 bool fdb_tx = flow_source_vport_representor(priv, act_priv);
    8996                 :          0 :                                 bool is_cx5 = sh->steering_format_version ==
    8997                 :            :                                     MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
    8998                 :            : 
    8999         [ #  # ]:          0 :                                 if (!fdb_tx && is_cx5)
    9000                 :            :                                         direction_error = true;
    9001         [ #  # ]:          0 :                         } else if (attr->ingress) {
    9002                 :            :                                 direction_error = true;
    9003                 :            :                         }
    9004                 :            :                         if (direction_error)
    9005                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    9006                 :            :                                                           RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
    9007                 :            :                                                           NULL,
    9008                 :            :                                                           "push VLAN action not supported "
    9009                 :            :                                                           "for ingress");
    9010                 :            :                 }
    9011         [ #  # ]:          0 :                 if (attr->ingress) {
    9012         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    9013                 :          0 :                                 return rte_flow_error_set
    9014                 :            :                                                 (error, ENOTSUP,
    9015                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
    9016                 :            :                                                  NULL, "encap is not supported"
    9017                 :            :                                                  " for ingress traffic");
    9018         [ #  # ]:          0 :                         else if ((action_flags & MLX5_FLOW_VLAN_ACTIONS) ==
    9019                 :            :                                         MLX5_FLOW_VLAN_ACTIONS)
    9020                 :          0 :                                 return rte_flow_error_set
    9021                 :            :                                                 (error, ENOTSUP,
    9022                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
    9023                 :            :                                                  NULL, "no support for "
    9024                 :            :                                                  "multiple VLAN actions");
    9025                 :            :                 }
    9026                 :            :         }
    9027                 :            :         /* Pop VLAN is not supported in egress except for NICs newer than CX5. */
    9028         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_POP_VLAN) {
    9029                 :          0 :                 struct mlx5_dev_ctx_shared *sh = priv->sh;
    9030                 :            :                 bool direction_error = false;
    9031                 :            : 
    9032         [ #  # ]:          0 :                 if (attr->transfer) {
    9033         [ #  # ]:          0 :                         bool fdb_tx = flow_source_vport_representor(priv, act_priv);
    9034                 :          0 :                         bool is_cx5 = sh->steering_format_version ==
    9035                 :            :                                         MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
    9036                 :            : 
    9037         [ #  # ]:          0 :                         if (fdb_tx && is_cx5)
    9038                 :            :                                 direction_error = true;
    9039         [ #  # ]:          0 :                 } else if (attr->egress) {
    9040                 :            :                         direction_error = true;
    9041                 :            :                 }
    9042                 :            :                 if (direction_error)
    9043                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    9044                 :            :                                                 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
    9045                 :            :                                                 NULL,
    9046                 :            :                                                 "pop vlan action not supported for egress");
    9047                 :            :         }
    9048         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY) {
    9049         [ #  # ]:          0 :                 if ((action_flags & (MLX5_FLOW_FATE_ACTIONS &
    9050         [ #  # ]:          0 :                         ~MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)) &&
    9051                 :            :                         attr->ingress)
    9052                 :          0 :                         return rte_flow_error_set
    9053                 :            :                                 (error, ENOTSUP,
    9054                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    9055                 :            :                                 NULL, "fate action not supported for "
    9056                 :            :                                 "meter with policy");
    9057         [ #  # ]:          0 :                 if (attr->egress) {
    9058         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)
    9059                 :          0 :                                 return rte_flow_error_set
    9060                 :            :                                         (error, ENOTSUP,
    9061                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9062                 :            :                                         NULL, "modify header action in egress "
    9063                 :            :                                         "cannot be done before meter action");
    9064         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    9065                 :          0 :                                 return rte_flow_error_set
    9066                 :            :                                         (error, ENOTSUP,
    9067                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9068                 :            :                                         NULL, "encap action in egress "
    9069                 :            :                                         "cannot be done before meter action");
    9070         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
    9071                 :          0 :                                 return rte_flow_error_set
    9072                 :            :                                         (error, ENOTSUP,
    9073                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9074                 :            :                                         NULL, "push vlan action in egress "
    9075                 :            :                                         "cannot be done before meter action");
    9076                 :            :                 }
    9077                 :            :         }
    9078                 :            :         /*
    9079                 :            :          * Only support one ASO action in a single flow rule.
    9080                 :            :          * non-shared AGE + counter will fallback to use HW counter, no ASO hit object.
    9081                 :            :          * Group 0 uses HW counter for AGE too even if no counter action.
    9082                 :            :          */
    9083   [ #  #  #  # ]:          0 :         aso_mask = (action_flags & MLX5_FLOW_ACTION_METER && priv->sh->meter_aso_en) << 2 |
    9084   [ #  #  #  #  :          0 :                    (action_flags & MLX5_FLOW_ACTION_CT && priv->sh->ct_aso_en) << 1 |
                   #  # ]
    9085                 :          0 :                    (action_flags & MLX5_FLOW_ACTION_AGE &&
    9086         [ #  # ]:          0 :                     !(non_shared_age && count) &&
    9087   [ #  #  #  #  :          0 :                     (attr->group || (attr->transfer && priv->fdb_def_rule)) &&
             #  #  #  # ]
    9088         [ #  # ]:          0 :                     priv->sh->flow_hit_aso_en);
    9089         [ #  # ]:          0 :         if (rte_popcount64(aso_mask) > 1)
    9090                 :          0 :                 return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
    9091                 :            :                                           NULL, "unsupported combining AGE, METER, CT ASO actions in a single rule");
    9092                 :            :         /*
    9093                 :            :          * Hairpin flow will add one more TAG action in TX implicit mode.
    9094                 :            :          * In TX explicit mode, there will be no hairpin flow ID.
    9095                 :            :          */
    9096         [ #  # ]:          0 :         if (hairpin > 0)
    9097                 :          0 :                 rw_act_num += MLX5_ACT_NUM_SET_TAG;
    9098                 :            :         /* extra metadata enabled: one more TAG action will be add. */
    9099         [ #  # ]:          0 :         if (dev_conf->dv_flow_en &&
    9100   [ #  #  #  # ]:          0 :             dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    9101                 :          0 :             mlx5_flow_ext_mreg_supported(dev))
    9102                 :          0 :                 rw_act_num += MLX5_ACT_NUM_SET_TAG;
    9103         [ #  # ]:          0 :         if (rw_act_num >
    9104                 :            :                         flow_dv_modify_hdr_action_max(dev, is_root)) {
    9105                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9106                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    9107                 :            :                                           NULL, "too many header modify"
    9108                 :            :                                           " actions to support");
    9109                 :            :         }
    9110         [ #  # ]:          0 :         if (fdb_mirror) {
    9111   [ #  #  #  # ]:          0 :                 if (!priv->sh->cdev->config.hca_attr.reg_c_preserve &&
    9112         [ #  # ]:          0 :                     flow_source_vport_representor(priv, act_priv)) {
    9113                 :            :                         /* Eswitch egress mirror and modify flow has limitation on CX5 */
    9114         [ #  # ]:          0 :                         if (modify_after_mirror)
    9115                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    9116                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9117                 :            :                                                 "sample before modify action is not supported");
    9118         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_JUMP)
    9119                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    9120                 :            :                                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9121                 :            :                                                         "sample and jump action combination is not supported");
    9122                 :            :                 }
    9123         [ #  # ]:          0 :                 if (aso_mask > 0 && aso_after_sample && fdb_mirror)
    9124                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    9125                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9126                 :            :                                                   "sample before ASO action is not supported");
    9127         [ #  # ]:          0 :                 if (sub_action_flags & MLX5_FLOW_ACTION_PORT_ID) {
    9128                 :          0 :                         port_priv = mlx5_port_to_eswitch_info(sample_port_id, false);
    9129         [ #  # ]:          0 :                         if (flow_source_vport_representor(priv, port_priv)) {
    9130         [ #  # ]:          0 :                                 if (sub_action_flags & MLX5_FLOW_ACTION_ENCAP)
    9131                 :          0 :                                         return rte_flow_error_set(error, ENOTSUP,
    9132                 :            :                                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9133                 :            :                                                                 "mirror to rep port with encap is not supported");
    9134                 :            :                         } else {
    9135         [ #  # ]:          0 :                                 if (!(sub_action_flags & MLX5_FLOW_ACTION_ENCAP) &&
    9136         [ #  # ]:          0 :                                     (action_flags & MLX5_FLOW_ACTION_JUMP))
    9137                 :          0 :                                         return rte_flow_error_set(error, ENOTSUP,
    9138                 :            :                                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9139                 :            :                                                                 "mirror to wire port without encap is not supported");
    9140                 :            :                         }
    9141                 :            :                 }
    9142         [ #  # ]:          0 :                 if ((action_flags & MLX5_FLOW_ACTION_PORT_ID) &&
    9143                 :            :                     (action_flags & MLX5_FLOW_ACTION_ENCAP)) {
    9144                 :          0 :                         port_priv = mlx5_port_to_eswitch_info(port_id, false);
    9145         [ #  # ]:          0 :                         if (flow_source_vport_representor(priv, port_priv))
    9146                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    9147                 :            :                                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9148                 :            :                                                         "mirror to rep port with encap is not supported");
    9149                 :            :                 }
    9150                 :            :         }
    9151                 :            :         /*
    9152                 :            :          * Validation the NIC Egress flow on representor, except implicit
    9153                 :            :          * hairpin default egress flow with TX_QUEUE item, other flows not
    9154                 :            :          * work due to metadata regC0 mismatch.
    9155                 :            :          */
    9156   [ #  #  #  #  :          0 :         if (attr->egress && priv->representor && !(item_flags & MLX5_FLOW_ITEM_SQ))
                   #  # ]
    9157                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    9158                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    9159                 :            :                                           NULL,
    9160                 :            :                                           "NIC egress rules on representors"
    9161                 :            :                                           " is not supported");
    9162                 :            :         return 0;
    9163                 :            : }
    9164                 :            : 
    9165                 :            : /**
    9166                 :            :  * Internal preparation function. Allocates the DV flow size,
    9167                 :            :  * this size is constant.
    9168                 :            :  *
    9169                 :            :  * @param[in] dev
    9170                 :            :  *   Pointer to the rte_eth_dev structure.
    9171                 :            :  * @param[in] attr
    9172                 :            :  *   Pointer to the flow attributes.
    9173                 :            :  * @param[in] items
    9174                 :            :  *   Pointer to the list of items.
    9175                 :            :  * @param[in] actions
    9176                 :            :  *   Pointer to the list of actions.
    9177                 :            :  * @param[out] error
    9178                 :            :  *   Pointer to the error structure.
    9179                 :            :  *
    9180                 :            :  * @return
    9181                 :            :  *   Pointer to mlx5_flow object on success,
    9182                 :            :  *   otherwise NULL and rte_errno is set.
    9183                 :            :  */
    9184                 :            : static struct mlx5_flow *
    9185                 :          0 : flow_dv_prepare(struct rte_eth_dev *dev,
    9186                 :            :                 const struct rte_flow_attr *attr __rte_unused,
    9187                 :            :                 const struct rte_flow_item items[] __rte_unused,
    9188                 :            :                 const struct rte_flow_action actions[] __rte_unused,
    9189                 :            :                 struct rte_flow_error *error)
    9190                 :            : {
    9191                 :          0 :         uint32_t handle_idx = 0;
    9192                 :            :         struct mlx5_flow *dev_flow;
    9193                 :            :         struct mlx5_flow_handle *dev_handle;
    9194                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9195                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
    9196                 :            : 
    9197                 :            :         MLX5_ASSERT(wks);
    9198                 :          0 :         wks->skip_matcher_reg = 0;
    9199                 :          0 :         wks->policy = NULL;
    9200                 :          0 :         wks->final_policy = NULL;
    9201                 :          0 :         wks->vport_meta_tag = 0;
    9202                 :            :         /* In case of corrupting the memory. */
    9203         [ #  # ]:          0 :         if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) {
    9204                 :          0 :                 rte_flow_error_set(error, ENOSPC,
    9205                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9206                 :            :                                    "not free temporary device flow");
    9207                 :          0 :                 return NULL;
    9208                 :            :         }
    9209                 :          0 :         dev_handle = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
    9210                 :            :                                    &handle_idx);
    9211         [ #  # ]:          0 :         if (!dev_handle) {
    9212                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9213                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9214                 :            :                                    "not enough memory to create flow handle");
    9215                 :          0 :                 return NULL;
    9216                 :            :         }
    9217                 :            :         MLX5_ASSERT(wks->flow_idx < RTE_DIM(wks->flows));
    9218                 :          0 :         dev_flow = &wks->flows[wks->flow_idx++];
    9219                 :            :         memset(dev_flow, 0, sizeof(*dev_flow));
    9220                 :          0 :         dev_flow->handle = dev_handle;
    9221                 :          0 :         dev_flow->handle_idx = handle_idx;
    9222                 :          0 :         dev_flow->dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);
    9223                 :          0 :         dev_flow->ingress = attr->ingress;
    9224                 :          0 :         dev_flow->dv.transfer = attr->transfer;
    9225                 :          0 :         return dev_flow;
    9226                 :            : }
    9227                 :            : 
    9228                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
    9229                 :            : /**
    9230                 :            :  * Sanity check for match mask and value. Similar to check_valid_spec() in
    9231                 :            :  * kernel driver. If unmasked bit is present in value, it returns failure.
    9232                 :            :  *
    9233                 :            :  * @param match_mask
    9234                 :            :  *   pointer to match mask buffer.
    9235                 :            :  * @param match_value
    9236                 :            :  *   pointer to match value buffer.
    9237                 :            :  *
    9238                 :            :  * @return
    9239                 :            :  *   0 if valid, -EINVAL otherwise.
    9240                 :            :  */
    9241                 :            : static int
    9242                 :            : flow_dv_check_valid_spec(void *match_mask, void *match_value)
    9243                 :            : {
    9244                 :            :         uint8_t *m = match_mask;
    9245                 :            :         uint8_t *v = match_value;
    9246                 :            :         unsigned int i;
    9247                 :            : 
    9248                 :            :         for (i = 0; i < MLX5_ST_SZ_BYTES(fte_match_param); ++i) {
    9249                 :            :                 if (v[i] & ~m[i]) {
    9250                 :            :                         DRV_LOG(ERR,
    9251                 :            :                                 "match_value differs from match_criteria"
    9252                 :            :                                 " %p[%u] != %p[%u]",
    9253                 :            :                                 match_value, i, match_mask, i);
    9254                 :            :                         return -EINVAL;
    9255                 :            :                 }
    9256                 :            :         }
    9257                 :            :         return 0;
    9258                 :            : }
    9259                 :            : #endif
    9260                 :            : 
    9261                 :            : /**
    9262                 :            :  * Add match of ip_version.
    9263                 :            :  *
    9264                 :            :  * @param[in] group
    9265                 :            :  *   Flow group.
    9266                 :            :  * @param[in] headers_v
    9267                 :            :  *   Values header pointer.
    9268                 :            :  * @param[in] headers_m
    9269                 :            :  *   Masks header pointer.
    9270                 :            :  * @param[in] ip_version
    9271                 :            :  *   The IP version to set.
    9272                 :            :  */
    9273                 :            : static inline void
    9274                 :          0 : flow_dv_set_match_ip_version(uint32_t group,
    9275                 :            :                              void *headers_v,
    9276                 :            :                              uint32_t key_type,
    9277                 :            :                              uint8_t ip_version)
    9278                 :            : {
    9279   [ #  #  #  # ]:          0 :         if (group == 0 && (key_type & MLX5_SET_MATCHER_M))
    9280         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 0xf);
    9281                 :            :         else
    9282         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version,
    9283                 :            :                          ip_version);
    9284         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, 0);
    9285                 :          0 : }
    9286                 :            : 
    9287                 :            : /**
    9288                 :            :  * Add Ethernet item to the value.
    9289                 :            :  *
    9290                 :            :  * @param[in, out] key
    9291                 :            :  *   Flow matcher value.
    9292                 :            :  * @param[in] item
    9293                 :            :  *   Flow pattern to translate.
    9294                 :            :  * @param[in] inner
    9295                 :            :  *   Item is inner pattern.
    9296                 :            :  * @param[in] grpup
    9297                 :            :  *   Flow matcher group.
    9298                 :            :  * @param[in] key_type
    9299                 :            :  *   Set flow matcher mask or value.
    9300                 :            :  */
    9301                 :            : static void
    9302                 :          0 : flow_dv_translate_item_eth(void *key, const struct rte_flow_item *item,
    9303                 :            :                            int inner, uint32_t group, uint32_t key_type)
    9304                 :            : {
    9305                 :          0 :         const struct rte_flow_item_eth *eth_vv = item->spec;
    9306                 :            :         const struct rte_flow_item_eth *eth_m;
    9307                 :            :         const struct rte_flow_item_eth *eth_v;
    9308                 :          0 :         const struct rte_flow_item_eth nic_mask = {
    9309                 :            :                 .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    9310                 :            :                 .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    9311                 :            :                 .hdr.ether_type = RTE_BE16(0xffff),
    9312                 :            :                 .has_vlan = 0,
    9313                 :            :         };
    9314                 :            :         void *hdrs_v;
    9315                 :            :         char *l24_v;
    9316                 :            :         unsigned int i;
    9317                 :            : 
    9318   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9319                 :          0 :                 return;
    9320   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, eth_v, eth_m, &nic_mask);
             #  #  #  # ]
    9321         [ #  # ]:          0 :         if (!eth_vv)
    9322                 :            :                 eth_vv = eth_v;
    9323         [ #  # ]:          0 :         if (inner)
    9324                 :          0 :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
    9325                 :            :         else
    9326                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9327                 :            :         /* The value must be in the range of the mask. */
    9328                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, dmac_47_16);
    9329         [ #  # ]:          0 :         for (i = 0; i < sizeof(eth_m->hdr.dst_addr); ++i)
    9330                 :          0 :                 l24_v[i] = eth_m->hdr.dst_addr.addr_bytes[i] & eth_v->hdr.dst_addr.addr_bytes[i];
    9331                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, smac_47_16);
    9332                 :            :         /* The value must be in the range of the mask. */
    9333         [ #  # ]:          0 :         for (i = 0; i < sizeof(eth_m->hdr.dst_addr); ++i)
    9334                 :          0 :                 l24_v[i] = eth_m->hdr.src_addr.addr_bytes[i] & eth_v->hdr.src_addr.addr_bytes[i];
    9335                 :            :         /*
    9336                 :            :          * HW supports match on one Ethertype, the Ethertype following the last
    9337                 :            :          * VLAN tag of the packet (see PRM).
    9338                 :            :          * Set match on ethertype only if ETH header is not followed by VLAN.
    9339                 :            :          * HW is optimized for IPv4/IPv6. In such cases, avoid setting
    9340                 :            :          * ethertype, and use ip_version field instead.
    9341                 :            :          * eCPRI over Ether layer will use type value 0xAEFE.
    9342                 :            :          */
    9343         [ #  # ]:          0 :         if (eth_m->hdr.ether_type == 0xFFFF) {
    9344                 :          0 :                 rte_be16_t type = eth_v->hdr.ether_type;
    9345                 :            : 
    9346                 :            :                 /*
    9347                 :            :                  * When set the matcher mask, refer to the original spec
    9348                 :            :                  * value.
    9349                 :            :                  */
    9350         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M) {
    9351         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9352                 :          0 :                         type = eth_vv->hdr.ether_type;
    9353                 :            :                 }
    9354                 :            :                 /* Set cvlan_tag mask for any single\multi\un-tagged case. */
    9355   [ #  #  #  #  :          0 :                 switch (type) {
                      # ]
    9356                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_VLAN):
    9357         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9358                 :          0 :                         return;
    9359                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_QINQ):
    9360         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9361                 :          0 :                         return;
    9362                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV4):
    9363                 :          0 :                         flow_dv_set_match_ip_version(group, hdrs_v, key_type,
    9364                 :            :                                                      4);
    9365                 :          0 :                         return;
    9366                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV6):
    9367                 :          0 :                         flow_dv_set_match_ip_version(group, hdrs_v, key_type,
    9368                 :            :                                                      6);
    9369                 :          0 :                         return;
    9370                 :            :                 default:
    9371                 :            :                         break;
    9372                 :            :                 }
    9373                 :            :         }
    9374                 :            :         /*
    9375                 :            :          * Only SW steering value should refer to the mask value.
    9376                 :            :          * Other cases are using the fake masks, just ignore the mask.
    9377                 :            :          */
    9378   [ #  #  #  # ]:          0 :         if (eth_v->has_vlan && eth_m->has_vlan) {
    9379                 :            :                 /*
    9380                 :            :                  * Here, when also has_more_vlan field in VLAN item is
    9381                 :            :                  * not set, only single-tagged packets will be matched.
    9382                 :            :                  */
    9383         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9384   [ #  #  #  # ]:          0 :                 if (key_type != MLX5_SET_MATCHER_HS_M && eth_vv->has_vlan)
    9385                 :            :                         return;
    9386                 :            :         }
    9387                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
    9388                 :          0 :         *(uint16_t *)(l24_v) = eth_m->hdr.ether_type & eth_v->hdr.ether_type;
    9389                 :            : }
    9390                 :            : 
    9391                 :            : /**
    9392                 :            :  * Add VLAN item to the value.
    9393                 :            :  *
    9394                 :            :  * @param[in, out] key
    9395                 :            :  *   Flow matcher value.
    9396                 :            :  * @param[in] item
    9397                 :            :  *   Flow pattern to translate.
    9398                 :            :  * @param[in] inner
    9399                 :            :  *   Item is inner pattern.
    9400                 :            :  * @param[in] wks
    9401                 :            :  *   Item workspace.
    9402                 :            :  * @param[in] key_type
    9403                 :            :  *   Set flow matcher mask or value.
    9404                 :            :  */
    9405                 :            : static void
    9406                 :          0 : flow_dv_translate_item_vlan(void *key, const struct rte_flow_item *item,
    9407                 :            :                             int inner, struct mlx5_dv_matcher_workspace *wks,
    9408                 :            :                             uint32_t key_type)
    9409                 :            : {
    9410                 :            :         const struct rte_flow_item_vlan *vlan_m;
    9411                 :            :         const struct rte_flow_item_vlan *vlan_v;
    9412                 :          0 :         const struct rte_flow_item_vlan *vlan_vv = item->spec;
    9413                 :            :         void *hdrs_v;
    9414                 :            :         uint16_t tci_v;
    9415                 :            : 
    9416         [ #  # ]:          0 :         if (inner) {
    9417                 :          0 :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
    9418                 :            :         } else {
    9419                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9420                 :            :                 /*
    9421                 :            :                  * This is workaround, masks are not supported,
    9422                 :            :                  * and pre-validated.
    9423                 :            :                  */
    9424         [ #  # ]:          0 :                 if (vlan_vv)
    9425         [ #  # ]:          0 :                         wks->vlan_tag = rte_be_to_cpu_16(vlan_vv->hdr.vlan_tci) & 0x0fff;
    9426                 :            :         }
    9427                 :            :         /*
    9428                 :            :          * When VLAN item exists in flow, mark packet as tagged,
    9429                 :            :          * even if TCI is not specified.
    9430                 :            :          */
    9431   [ #  #  #  # ]:          0 :         if (!MLX5_GET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag))
    9432         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9433   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9434                 :            :                 return;
    9435   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, vlan_v, vlan_m,
             #  #  #  # ]
    9436                 :            :                          &rte_flow_item_vlan_mask);
    9437         [ #  # ]:          0 :         tci_v = rte_be_to_cpu_16(vlan_m->hdr.vlan_tci & vlan_v->hdr.vlan_tci);
    9438         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_vid, tci_v);
    9439         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_cfi, tci_v >> 12);
    9440         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_prio, tci_v >> 13);
    9441                 :            :         /*
    9442                 :            :          * HW is optimized for IPv4/IPv6. In such cases, avoid setting
    9443                 :            :          * ethertype, and use ip_version field instead.
    9444                 :            :          */
    9445         [ #  # ]:          0 :         if (vlan_m->hdr.eth_proto == 0xFFFF) {
    9446                 :          0 :                 rte_be16_t inner_type = vlan_v->hdr.eth_proto;
    9447                 :            : 
    9448                 :            :                 /*
    9449                 :            :                  * When set the matcher mask, refer to the original spec
    9450                 :            :                  * value.
    9451                 :            :                  */
    9452         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M)
    9453                 :          0 :                         inner_type = vlan_vv->hdr.eth_proto;
    9454   [ #  #  #  # ]:          0 :                 switch (inner_type) {
    9455                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_VLAN):
    9456         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9457         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_V)
    9458         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
    9459                 :            :                                          cvlan_tag, 0);
    9460                 :          0 :                         return;
    9461                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV4):
    9462                 :          0 :                         flow_dv_set_match_ip_version
    9463                 :            :                                 (wks->group, hdrs_v, key_type, 4);
    9464                 :          0 :                         return;
    9465                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV6):
    9466                 :          0 :                         flow_dv_set_match_ip_version
    9467                 :            :                                 (wks->group, hdrs_v, key_type, 6);
    9468                 :          0 :                         return;
    9469                 :            :                 default:
    9470                 :            :                         break;
    9471                 :            :                 }
    9472                 :            :         }
    9473   [ #  #  #  # ]:          0 :         if (vlan_m->has_more_vlan && vlan_v->has_more_vlan) {
    9474         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9475                 :            :                 /* Only one vlan_tag bit can be set. */
    9476         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_V)
    9477         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0);
    9478                 :          0 :                 return;
    9479                 :            :         }
    9480   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, ethertype,
    9481                 :            :                  rte_be_to_cpu_16(vlan_m->hdr.eth_proto & vlan_v->hdr.eth_proto));
    9482                 :            : }
    9483                 :            : 
    9484                 :            : /**
    9485                 :            :  * Add IPV4 item to the value.
    9486                 :            :  *
    9487                 :            :  * @param[in, out] key
    9488                 :            :  *   Flow matcher value.
    9489                 :            :  * @param[in] item
    9490                 :            :  *   Flow pattern to translate.
    9491                 :            :  * @param[in] inner
    9492                 :            :  *   Item is inner pattern.
    9493                 :            :  * @param[in] group
    9494                 :            :  *   The group to insert the rule.
    9495                 :            :  * @param[in] key_type
    9496                 :            :  *   Set flow matcher mask or value.
    9497                 :            :  */
    9498                 :            : static void
    9499                 :          0 : flow_dv_translate_item_ipv4(void *key, const struct rte_flow_item *item,
    9500                 :            :                             int inner, uint32_t group, uint32_t key_type)
    9501                 :            : {
    9502                 :            :         const struct rte_flow_item_ipv4 *ipv4_m;
    9503                 :            :         const struct rte_flow_item_ipv4 *ipv4_v;
    9504                 :          0 :         const struct rte_flow_item_ipv4 nic_mask = {
    9505                 :            :                 .hdr = {
    9506                 :            :                         .src_addr = RTE_BE32(0xffffffff),
    9507                 :            :                         .dst_addr = RTE_BE32(0xffffffff),
    9508                 :            :                         .type_of_service = 0xff,
    9509                 :            :                         .next_proto_id = 0xff,
    9510                 :            :                         .time_to_live = 0xff,
    9511                 :            :                 },
    9512                 :            :         };
    9513                 :            :         void *headers_v;
    9514                 :            :         char *l24_v;
    9515                 :            :         uint8_t tos;
    9516                 :            : 
    9517         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9518                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9519                 :          0 :         flow_dv_set_match_ip_version(group, headers_v, key_type, 4);
    9520   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9521                 :          0 :                 return;
    9522   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv4_v, ipv4_m, &nic_mask);
             #  #  #  # ]
    9523                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9524                 :            :                              dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
    9525                 :          0 :         *(uint32_t *)l24_v = ipv4_m->hdr.dst_addr & ipv4_v->hdr.dst_addr;
    9526                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9527                 :            :                           src_ipv4_src_ipv6.ipv4_layout.ipv4);
    9528                 :          0 :         *(uint32_t *)l24_v = ipv4_m->hdr.src_addr & ipv4_v->hdr.src_addr;
    9529                 :          0 :         tos = ipv4_m->hdr.type_of_service & ipv4_v->hdr.type_of_service;
    9530         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ipv4_ihl,
    9531                 :            :                  ipv4_v->hdr.ihl & ipv4_m->hdr.ihl);
    9532         [ #  # ]:          0 :         if (key_type == MLX5_SET_MATCHER_SW_M)
    9533         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
    9534                 :            :                          ipv4_v->hdr.type_of_service);
    9535         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, tos);
    9536         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, tos >> 2);
    9537         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9538                 :            :                  ipv4_v->hdr.next_proto_id & ipv4_m->hdr.next_proto_id);
    9539         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit,
    9540                 :            :                  ipv4_v->hdr.time_to_live & ipv4_m->hdr.time_to_live);
    9541         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
    9542                 :            :                  !!(ipv4_v->hdr.fragment_offset & ipv4_m->hdr.fragment_offset));
    9543                 :            : }
    9544                 :            : 
    9545                 :            : /**
    9546                 :            :  * Add IPV6 item to the value.
    9547                 :            :  *
    9548                 :            :  * @param[in, out] key
    9549                 :            :  *   Flow matcher value.
    9550                 :            :  * @param[in] item
    9551                 :            :  *   Flow pattern to translate.
    9552                 :            :  * @param[in] inner
    9553                 :            :  *   Item is inner pattern.
    9554                 :            :  * @param[in] group
    9555                 :            :  *   The group to insert the rule.
    9556                 :            :  * @param[in] key_type
    9557                 :            :  *   Set flow matcher mask or value.
    9558                 :            :  */
    9559                 :            : static void
    9560                 :          0 : flow_dv_translate_item_ipv6(void *key, const struct rte_flow_item *item,
    9561                 :            :                             int inner, uint32_t group, uint32_t key_type)
    9562                 :            : {
    9563                 :            :         const struct rte_flow_item_ipv6 *ipv6_m;
    9564                 :            :         const struct rte_flow_item_ipv6 *ipv6_v;
    9565                 :          0 :         const struct rte_flow_item_ipv6 nic_mask = {
    9566                 :            :                 .hdr = {
    9567                 :            :                         .src_addr = RTE_IPV6_MASK_FULL,
    9568                 :            :                         .dst_addr = RTE_IPV6_MASK_FULL,
    9569                 :            :                         .vtc_flow = RTE_BE32(0xffffffff),
    9570                 :            :                         .proto = 0xff,
    9571                 :            :                         .hop_limits = 0xff,
    9572                 :            :                 },
    9573                 :            :         };
    9574                 :            :         void *headers_v;
    9575                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9576                 :            :         char *l24_v;
    9577                 :            :         uint32_t vtc_v;
    9578                 :            :         int i;
    9579                 :            :         int size;
    9580                 :            : 
    9581         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9582                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9583                 :          0 :         flow_dv_set_match_ip_version(group, headers_v, key_type, 6);
    9584   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9585                 :          0 :                 return;
    9586   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv6_v, ipv6_m, &nic_mask);
             #  #  #  # ]
    9587                 :            :         size = sizeof(ipv6_m->hdr.dst_addr);
    9588                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9589                 :            :                              dst_ipv4_dst_ipv6.ipv6_layout.ipv6);
    9590         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9591                 :          0 :                 l24_v[i] = ipv6_m->hdr.dst_addr.a[i] & ipv6_v->hdr.dst_addr.a[i];
    9592                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9593                 :            :                              src_ipv4_src_ipv6.ipv6_layout.ipv6);
    9594         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9595                 :          0 :                 l24_v[i] = ipv6_m->hdr.src_addr.a[i] & ipv6_v->hdr.src_addr.a[i];
    9596                 :            :         /* TOS. */
    9597         [ #  # ]:          0 :         vtc_v = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow & ipv6_v->hdr.vtc_flow);
    9598         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, vtc_v >> 20);
    9599         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, vtc_v >> 22);
    9600                 :            :         /* Label. */
    9601         [ #  # ]:          0 :         if (inner)
    9602         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc, misc_v, inner_ipv6_flow_label,
    9603                 :            :                          vtc_v);
    9604                 :            :         else
    9605         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc, misc_v, outer_ipv6_flow_label,
    9606                 :            :                          vtc_v);
    9607                 :            :         /* Protocol. */
    9608         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9609                 :            :                  ipv6_v->hdr.proto & ipv6_m->hdr.proto);
    9610                 :            :         /* Hop limit. */
    9611         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit,
    9612                 :            :                  ipv6_v->hdr.hop_limits & ipv6_m->hdr.hop_limits);
    9613         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
    9614                 :            :                  !!(ipv6_v->has_frag_ext & ipv6_m->has_frag_ext));
    9615                 :            : }
    9616                 :            : 
    9617                 :            : /**
    9618                 :            :  * Add IPV6 fragment extension item to the value.
    9619                 :            :  *
    9620                 :            :  * @param[in, out] key
    9621                 :            :  *   Flow matcher value.
    9622                 :            :  * @param[in] item
    9623                 :            :  *   Flow pattern to translate.
    9624                 :            :  * @param[in] inner
    9625                 :            :  *   Item is inner pattern.
    9626                 :            :  * @param[in] key_type
    9627                 :            :  *   Set flow matcher mask or value.
    9628                 :            :  */
    9629                 :            : static void
    9630                 :          0 : flow_dv_translate_item_ipv6_frag_ext(void *key,
    9631                 :            :                                      const struct rte_flow_item *item,
    9632                 :            :                                      int inner, uint32_t key_type)
    9633                 :            : {
    9634                 :            :         const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_m;
    9635                 :            :         const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_v;
    9636                 :          0 :         const struct rte_flow_item_ipv6_frag_ext nic_mask = {
    9637                 :            :                 .hdr = {
    9638                 :            :                         .next_header = 0xff,
    9639                 :            :                         .frag_data = RTE_BE16(0xffff),
    9640                 :            :                 },
    9641                 :            :         };
    9642                 :            :         void *headers_v;
    9643                 :            : 
    9644         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9645                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9646                 :            :         /* IPv6 fragment extension item exists, so packet is IP fragment. */
    9647         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 1);
    9648   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9649                 :          0 :                 return;
    9650   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv6_frag_ext_v,
             #  #  #  # ]
    9651                 :            :                          ipv6_frag_ext_m, &nic_mask);
    9652         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9653                 :            :                  ipv6_frag_ext_v->hdr.next_header &
    9654                 :            :                  ipv6_frag_ext_m->hdr.next_header);
    9655                 :            : }
    9656                 :            : 
    9657                 :            : /**
    9658                 :            :  * Add TCP item to the value.
    9659                 :            :  *
    9660                 :            :  * @param[in, out] key
    9661                 :            :  *   Flow matcher value.
    9662                 :            :  * @param[in] item
    9663                 :            :  *   Flow pattern to translate.
    9664                 :            :  * @param[in] inner
    9665                 :            :  *   Item is inner pattern.
    9666                 :            :  * @param[in] key_type
    9667                 :            :  *   Set flow matcher mask or value.
    9668                 :            :  */
    9669                 :            : static void
    9670                 :          0 : flow_dv_translate_item_tcp(void *key, const struct rte_flow_item *item,
    9671                 :            :                            int inner, uint32_t key_type)
    9672                 :            : {
    9673                 :            :         const struct rte_flow_item_tcp *tcp_m;
    9674                 :            :         const struct rte_flow_item_tcp *tcp_v;
    9675                 :            :         void *headers_v;
    9676                 :            : 
    9677         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9678                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9679         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9680         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9681                 :            :                          ip_protocol, 0xff);
    9682                 :            :         else
    9683         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9684                 :            :                          ip_protocol, IPPROTO_TCP);
    9685   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9686                 :            :                 return;
    9687   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, tcp_v, tcp_m,
             #  #  #  # ]
    9688                 :            :                          &rte_flow_item_tcp_mask);
    9689   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,
    9690                 :            :                  rte_be_to_cpu_16(tcp_v->hdr.src_port & tcp_m->hdr.src_port));
    9691   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,
    9692                 :            :                  rte_be_to_cpu_16(tcp_v->hdr.dst_port & tcp_m->hdr.dst_port));
    9693         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
    9694                 :            :                  tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags);
    9695                 :            : }
    9696                 :            : 
    9697                 :            : /**
    9698                 :            :  * Add ESP item to the value.
    9699                 :            :  *
    9700                 :            :  * @param[in, out] key
    9701                 :            :  *   Flow matcher value.
    9702                 :            :  * @param[in] item
    9703                 :            :  *   Flow pattern to translate.
    9704                 :            :  * @param[in] inner
    9705                 :            :  *   Item is inner pattern.
    9706                 :            :  * @param[in] key_type
    9707                 :            :  *   Set flow matcher mask or value.
    9708                 :            :  */
    9709                 :            : static void
    9710                 :          0 : flow_dv_translate_item_esp(void *key, const struct rte_flow_item *item,
    9711                 :            :                            int inner, uint32_t key_type)
    9712                 :            : {
    9713                 :            :         const struct rte_flow_item_esp *esp_m;
    9714                 :            :         const struct rte_flow_item_esp *esp_v;
    9715                 :            :         void *headers_v;
    9716                 :            :         char *spi_v;
    9717                 :            : 
    9718         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9719                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9720         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9721         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9722                 :            :                          ip_protocol, 0xff);
    9723                 :            :         else
    9724         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9725                 :            :                          ip_protocol, IPPROTO_ESP);
    9726   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9727                 :            :                 return;
    9728   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, esp_v, esp_m,
             #  #  #  # ]
    9729                 :            :                          &rte_flow_item_esp_mask);
    9730                 :            :         headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9731                 :            :         spi_v = inner ? MLX5_ADDR_OF(fte_match_set_misc, headers_v,
    9732         [ #  # ]:          0 :                                 inner_esp_spi) : MLX5_ADDR_OF(fte_match_set_misc
    9733                 :            :                                 , headers_v, outer_esp_spi);
    9734                 :          0 :         *(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
    9735                 :            : }
    9736                 :            : 
    9737                 :            : /**
    9738                 :            :  * Add UDP item to the value.
    9739                 :            :  *
    9740                 :            :  * @param[in, out] key
    9741                 :            :  *   Flow matcher value.
    9742                 :            :  * @param[in] item
    9743                 :            :  *   Flow pattern to translate.
    9744                 :            :  * @param[in] inner
    9745                 :            :  *   Item is inner pattern.
    9746                 :            :  * @param[in] key_type
    9747                 :            :  *   Set flow matcher mask or value.
    9748                 :            :  */
    9749                 :            : static void
    9750                 :          0 : flow_dv_translate_item_udp(void *key, const struct rte_flow_item *item,
    9751                 :            :                            int inner, struct mlx5_dv_matcher_workspace *wks,
    9752                 :            :                            uint32_t key_type)
    9753                 :            : {
    9754                 :            :         const struct rte_flow_item_udp *udp_m;
    9755                 :            :         const struct rte_flow_item_udp *udp_v;
    9756                 :            :         void *headers_v;
    9757                 :            : 
    9758         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9759                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9760         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9761         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9762                 :            :                          ip_protocol, 0xff);
    9763                 :            :         else
    9764         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9765                 :            :                          ip_protocol, IPPROTO_UDP);
    9766   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9767                 :            :                 return;
    9768   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, udp_v, udp_m,
             #  #  #  # ]
    9769                 :            :                          &rte_flow_item_udp_mask);
    9770   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
    9771                 :            :                  rte_be_to_cpu_16(udp_v->hdr.src_port & udp_m->hdr.src_port));
    9772   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
    9773                 :            :                  rte_be_to_cpu_16(udp_v->hdr.dst_port & udp_m->hdr.dst_port));
    9774                 :            :         /* Force get UDP dport in case to be used in VXLAN translate. */
    9775         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW) {
    9776                 :          0 :                 udp_v = item->spec;
    9777         [ #  # ]:          0 :                 wks->udp_dport = rte_be_to_cpu_16(udp_v->hdr.dst_port &
    9778                 :            :                                                   udp_m->hdr.dst_port);
    9779                 :            :         }
    9780                 :            : }
    9781                 :            : 
    9782                 :            : /**
    9783                 :            :  * Add GRE optional Key item to the value.
    9784                 :            :  *
    9785                 :            :  * @param[in, out] key
    9786                 :            :  *   Flow matcher value.
    9787                 :            :  * @param[in] item
    9788                 :            :  *   Flow pattern to translate.
    9789                 :            :  * @param[in] inner
    9790                 :            :  *   Item is inner pattern.
    9791                 :            :  */
    9792                 :            : static void
    9793                 :          0 : flow_dv_translate_item_gre_key(void *key, const struct rte_flow_item *item,
    9794                 :            :                                uint32_t key_type)
    9795                 :            : {
    9796                 :            :         const rte_be32_t *key_m;
    9797                 :            :         const rte_be32_t *key_v;
    9798                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9799                 :          0 :         rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
    9800                 :            : 
    9801                 :            :         /* GRE K bit must be on and should already be validated */
    9802         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
    9803   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9804                 :          0 :                 return;
    9805   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, key_v, key_m,
             #  #  #  # ]
    9806                 :            :                          &gre_key_default_mask);
    9807   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_key_h,
    9808                 :            :                  rte_be_to_cpu_32((*key_v) & (*key_m)) >> 8);
    9809   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_key_l,
    9810                 :            :                  rte_be_to_cpu_32((*key_v) & (*key_m)) & 0xFF);
    9811                 :            : }
    9812                 :            : 
    9813                 :            : /**
    9814                 :            :  * Add GRE item to the value.
    9815                 :            :  *
    9816                 :            :  * @param[in, out] key
    9817                 :            :  *   Flow matcher value.
    9818                 :            :  * @param[in] item
    9819                 :            :  *   Flow pattern to translate.
    9820                 :            :  * @param[in] pattern_flags
    9821                 :            :  *   Accumulated pattern flags.
    9822                 :            :  * @param[in] key_type
    9823                 :            :  *   Set flow matcher mask or value.
    9824                 :            :  */
    9825                 :            : static void
    9826                 :          0 : flow_dv_translate_item_gre(void *key, const struct rte_flow_item *item,
    9827                 :            :                            uint64_t pattern_flags, uint32_t key_type)
    9828                 :            : {
    9829                 :            :         static const struct rte_flow_item_gre empty_gre = {0,};
    9830                 :          0 :         const struct rte_flow_item_gre *gre_m = item->mask;
    9831                 :          0 :         const struct rte_flow_item_gre *gre_v = item->spec;
    9832                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9833                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9834                 :            :         struct {
    9835                 :            :                 union {
    9836                 :            :                         __extension__
    9837                 :            :                         struct {
    9838                 :            :                                 uint16_t version:3;
    9839                 :            :                                 uint16_t rsvd0:9;
    9840                 :            :                                 uint16_t s_present:1;
    9841                 :            :                                 uint16_t k_present:1;
    9842                 :            :                                 uint16_t rsvd_bit1:1;
    9843                 :            :                                 uint16_t c_present:1;
    9844                 :            :                         };
    9845                 :            :                         uint16_t value;
    9846                 :            :                 };
    9847                 :            :         } gre_crks_rsvd0_ver_m, gre_crks_rsvd0_ver_v;
    9848                 :            :         uint16_t protocol_m, protocol_v;
    9849                 :            : 
    9850                 :            :         /* Common logic to SWS/HWS */
    9851         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9852         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xff);
    9853                 :            :         else
    9854         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9855                 :            :                         IPPROTO_GRE);
    9856                 :            :         /* HWS mask logic only */
    9857         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_HS_M) {
    9858         [ #  # ]:          0 :                 if (!gre_m)
    9859                 :            :                         gre_m = &empty_gre;
    9860                 :            :                 gre_v = gre_m;
    9861         [ #  # ]:          0 :         } else if (!gre_v) {
    9862                 :            :                 gre_v = &empty_gre;
    9863                 :            :                 gre_m = &empty_gre;
    9864         [ #  # ]:          0 :         } else if (!gre_m) {
    9865                 :            :                 gre_m = &rte_flow_item_gre_mask;
    9866                 :            :         }
    9867                 :            :         /* SWS logic only */
    9868         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW_M)
    9869                 :            :                 gre_v = gre_m;
    9870         [ #  # ]:          0 :         gre_crks_rsvd0_ver_m.value = rte_be_to_cpu_16(gre_m->c_rsvd0_ver);
    9871         [ #  # ]:          0 :         gre_crks_rsvd0_ver_v.value = rte_be_to_cpu_16(gre_v->c_rsvd0_ver);
    9872         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_c_present,
    9873                 :            :                  gre_crks_rsvd0_ver_v.c_present &
    9874                 :            :                  gre_crks_rsvd0_ver_m.c_present);
    9875         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_k_present,
    9876                 :            :                  gre_crks_rsvd0_ver_v.k_present &
    9877                 :            :                  gre_crks_rsvd0_ver_m.k_present);
    9878         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_s_present,
    9879                 :            :                  gre_crks_rsvd0_ver_v.s_present &
    9880                 :            :                  gre_crks_rsvd0_ver_m.s_present);
    9881         [ #  # ]:          0 :         protocol_m = rte_be_to_cpu_16(gre_m->protocol);
    9882         [ #  # ]:          0 :         protocol_v = rte_be_to_cpu_16(gre_v->protocol);
    9883         [ #  # ]:          0 :         if (!protocol_m) {
    9884                 :            :                 /* Force next protocol to prevent matchers duplication */
    9885                 :            :                 protocol_v = mlx5_translate_tunnel_etypes(pattern_flags);
    9886                 :            :                 if (protocol_v)
    9887                 :            :                         protocol_m = 0xFFFF;
    9888                 :            :                 /* Restore the value to mask in mask case. */
    9889         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
    9890                 :            :                         protocol_v = protocol_m;
    9891                 :            :         }
    9892         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_protocol,
    9893                 :            :                  protocol_m & protocol_v);
    9894                 :          0 : }
    9895                 :            : 
    9896                 :            : /**
    9897                 :            :  * Add GRE optional items to the value.
    9898                 :            :  *
    9899                 :            :  * @param[in, out] key
    9900                 :            :  *   Flow matcher value.
    9901                 :            :  * @param[in] item
    9902                 :            :  *   Flow pattern to translate.
    9903                 :            :  * @param[in] gre_item
    9904                 :            :  *   Pointer to gre_item.
    9905                 :            :  * @param[in] pattern_flags
    9906                 :            :  *   Accumulated pattern flags.
    9907                 :            :  * @param[in] key_type
    9908                 :            :  *   Set flow matcher mask or value.
    9909                 :            :  */
    9910                 :            : static void
    9911                 :          0 : flow_dv_translate_item_gre_option(void *key,
    9912                 :            :                                   const struct rte_flow_item *item,
    9913                 :            :                                   const struct rte_flow_item *gre_item,
    9914                 :            :                                   uint64_t pattern_flags, uint32_t key_type)
    9915                 :            : {
    9916                 :            :         void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
    9917                 :          0 :         const struct rte_flow_item_gre_opt *option_m = item->mask;
    9918                 :          0 :         const struct rte_flow_item_gre_opt *option_v = item->spec;
    9919                 :          0 :         const struct rte_flow_item_gre *gre_m = gre_item->mask;
    9920                 :          0 :         const struct rte_flow_item_gre *gre_v = gre_item->spec;
    9921                 :            :         static const struct rte_flow_item_gre empty_gre = {0};
    9922                 :            :         struct rte_flow_item gre_key_item;
    9923                 :            :         uint16_t c_rsvd0_ver_m, c_rsvd0_ver_v;
    9924                 :            :         uint16_t protocol_m, protocol_v;
    9925                 :            : 
    9926                 :            :         /*
    9927                 :            :          * If only match key field, keep using misc for matching.
    9928                 :            :          * If need to match checksum or sequence, using misc5 and do
    9929                 :            :          * not need using misc.
    9930                 :            :          */
    9931         [ #  # ]:          0 :         if (!(option_m->sequence.sequence ||
    9932         [ #  # ]:          0 :               option_m->checksum_rsvd.checksum)) {
    9933                 :          0 :                 flow_dv_translate_item_gre(key, gre_item, pattern_flags, key_type);
    9934                 :          0 :                 gre_key_item.spec = &option_v->key.key;
    9935                 :          0 :                 gre_key_item.mask = &option_m->key.key;
    9936                 :          0 :                 flow_dv_translate_item_gre_key(key, &gre_key_item, key_type);
    9937                 :          0 :                 return;
    9938                 :            :         }
    9939         [ #  # ]:          0 :         if (!gre_v) {
    9940                 :            :                 gre_v = &empty_gre;
    9941                 :            :                 gre_m = &empty_gre;
    9942                 :            :         } else {
    9943         [ #  # ]:          0 :                 if (!gre_m)
    9944                 :            :                         gre_m = &rte_flow_item_gre_mask;
    9945                 :            :         }
    9946                 :          0 :         protocol_v = gre_v->protocol;
    9947                 :          0 :         protocol_m = gre_m->protocol;
    9948         [ #  # ]:          0 :         if (!protocol_m) {
    9949                 :            :                 /* Force next protocol to prevent matchers duplication */
    9950                 :            :                 uint16_t ether_type =
    9951                 :            :                         mlx5_translate_tunnel_etypes(pattern_flags);
    9952                 :            :                 if (ether_type) {
    9953         [ #  # ]:          0 :                         protocol_v = rte_be_to_cpu_16(ether_type);
    9954                 :            :                         protocol_m = UINT16_MAX;
    9955                 :            :                 }
    9956                 :            :         }
    9957                 :          0 :         c_rsvd0_ver_v = gre_v->c_rsvd0_ver;
    9958                 :          0 :         c_rsvd0_ver_m = gre_m->c_rsvd0_ver;
    9959         [ #  # ]:          0 :         if (option_m->sequence.sequence) {
    9960                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x1000);
    9961                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x1000);
    9962                 :            :         }
    9963         [ #  # ]:          0 :         if (option_m->key.key) {
    9964                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x2000);
    9965                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x2000);
    9966                 :            :         }
    9967         [ #  # ]:          0 :         if (option_m->checksum_rsvd.checksum) {
    9968                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x8000);
    9969                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x8000);
    9970                 :            :         }
    9971         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
    9972                 :            :                 c_rsvd0_ver_v = c_rsvd0_ver_m;
    9973                 :            :                 protocol_v = protocol_m;
    9974                 :            :                 option_v = option_m;
    9975                 :            :         }
    9976                 :            :         /*
    9977                 :            :          * Hardware parses GRE optional field into the fixed location,
    9978                 :            :          * do not need to adjust the tunnel dword indices.
    9979                 :            :          */
    9980   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0,
    9981                 :            :                  rte_be_to_cpu_32((c_rsvd0_ver_v | protocol_v << 16) &
    9982                 :            :                                   (c_rsvd0_ver_m | protocol_m << 16)));
    9983   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1,
    9984                 :            :                  rte_be_to_cpu_32(option_v->checksum_rsvd.checksum &
    9985                 :            :                                   option_m->checksum_rsvd.checksum));
    9986   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_2,
    9987                 :            :                  rte_be_to_cpu_32(option_v->key.key & option_m->key.key));
    9988   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_3,
    9989                 :            :                  rte_be_to_cpu_32(option_v->sequence.sequence &
    9990                 :            :                                   option_m->sequence.sequence));
    9991                 :            : }
    9992                 :            : 
    9993                 :            : /**
    9994                 :            :  * Add NVGRE item to matcher and to the value.
    9995                 :            :  *
    9996                 :            :  * @param[in, out] key
    9997                 :            :  *   Flow matcher value.
    9998                 :            :  * @param[in] item
    9999                 :            :  *   Flow pattern to translate.
   10000                 :            :  * @param[in] pattern_flags
   10001                 :            :  *   Accumulated pattern flags.
   10002                 :            :  * @param[in] key_type
   10003                 :            :  *   Set flow matcher mask or value.
   10004                 :            :  */
   10005                 :            : static void
   10006                 :          0 : flow_dv_translate_item_nvgre(void *key, const struct rte_flow_item *item,
   10007                 :            :                              unsigned long pattern_flags, uint32_t key_type)
   10008                 :            : {
   10009                 :            :         const struct rte_flow_item_nvgre *nvgre_m;
   10010                 :            :         const struct rte_flow_item_nvgre *nvgre_v;
   10011                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10012                 :            :         const char *tni_flow_id_m;
   10013                 :            :         const char *tni_flow_id_v;
   10014                 :            :         char *gre_key_v;
   10015                 :            :         int size;
   10016                 :            :         int i;
   10017                 :            : 
   10018                 :            :         /* For NVGRE, GRE header fields must be set with defined values. */
   10019                 :          0 :         const struct rte_flow_item_gre gre_spec = {
   10020                 :            :                 .c_rsvd0_ver = RTE_BE16(0x2000),
   10021                 :            :                 .protocol = RTE_BE16(RTE_ETHER_TYPE_TEB)
   10022                 :            :         };
   10023                 :          0 :         const struct rte_flow_item_gre gre_mask = {
   10024                 :            :                 .c_rsvd0_ver = RTE_BE16(0xB000),
   10025                 :            :                 .protocol = RTE_BE16(UINT16_MAX),
   10026                 :            :         };
   10027                 :          0 :         const struct rte_flow_item gre_item = {
   10028                 :            :                 .spec = &gre_spec,
   10029                 :            :                 .mask = &gre_mask,
   10030                 :            :                 .last = NULL,
   10031                 :            :         };
   10032                 :          0 :         flow_dv_translate_item_gre(key, &gre_item, pattern_flags, key_type);
   10033   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10034                 :          0 :                 return;
   10035   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, nvgre_v, nvgre_m,
             #  #  #  # ]
   10036                 :            :                     &rte_flow_item_nvgre_mask);
   10037                 :          0 :         tni_flow_id_m = (const char *)nvgre_m->tni;
   10038                 :          0 :         tni_flow_id_v = (const char *)nvgre_v->tni;
   10039                 :            :         size = sizeof(nvgre_m->tni) + sizeof(nvgre_m->flow_id);
   10040                 :          0 :         gre_key_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, gre_key_h);
   10041         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   10042                 :          0 :                 gre_key_v[i] = tni_flow_id_m[i] & tni_flow_id_v[i];
   10043                 :            : }
   10044                 :            : 
   10045                 :            : /**
   10046                 :            :  * Add VXLAN item to the value.
   10047                 :            :  *
   10048                 :            :  * @param[in] dev
   10049                 :            :  *   Pointer to the Ethernet device structure.
   10050                 :            :  * @param[in] attr
   10051                 :            :  *   Flow rule attributes.
   10052                 :            :  * @param[in, out] key
   10053                 :            :  *   Flow matcher value.
   10054                 :            :  * @param[in] item
   10055                 :            :  *   Flow pattern to translate.
   10056                 :            :  * @param[in] inner
   10057                 :            :  *   Item is inner pattern.
   10058                 :            :  * @param[in] wks
   10059                 :            :  *   Matcher workspace.
   10060                 :            :  * @param[in] key_type
   10061                 :            :  *   Set flow matcher mask or value.
   10062                 :            :  */
   10063                 :            : static void
   10064                 :          0 : flow_dv_translate_item_vxlan(struct rte_eth_dev *dev,
   10065                 :            :                              const struct rte_flow_attr *attr,
   10066                 :            :                              void *key, const struct rte_flow_item *item,
   10067                 :            :                              int inner, struct mlx5_dv_matcher_workspace *wks,
   10068                 :            :                              uint32_t key_type)
   10069                 :            : {
   10070                 :            :         const struct rte_flow_item_vxlan *vxlan_m;
   10071                 :            :         const struct rte_flow_item_vxlan *vxlan_v;
   10072                 :            :         void *headers_v;
   10073                 :            :         void *misc_v;
   10074                 :            :         void *misc5_v;
   10075                 :            :         uint32_t tunnel_v;
   10076                 :            :         char *vni_v;
   10077                 :            :         uint16_t dport;
   10078                 :            :         int size;
   10079                 :            :         int i;
   10080                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10081                 :          0 :         const struct rte_flow_item_vxlan nic_mask = {
   10082                 :            :                 .hdr.vni =  { 0xff, 0xff, 0xff },
   10083                 :            :                 .hdr.rsvd1 = 0xff,
   10084                 :            :         };
   10085                 :            : 
   10086                 :            :         misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
   10087         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   10088                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10089         [ #  # ]:          0 :         dport = item->type == RTE_FLOW_ITEM_TYPE_VXLAN ?
   10090                 :            :                 MLX5_UDP_PORT_VXLAN : MLX5_UDP_PORT_VXLAN_GPE;
   10091   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10092         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10093         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10094                 :            :                                  udp_dport, 0xFFFF);
   10095                 :            :                 else
   10096         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10097                 :            :                                  udp_dport, dport);
   10098                 :            :         }
   10099                 :            :         /*
   10100                 :            :          * Read the UDP dport to check if the value satisfies the VXLAN
   10101                 :            :          * matching with MISC5 for CX5.
   10102                 :            :          */
   10103         [ #  # ]:          0 :         if (wks->udp_dport)
   10104                 :            :                 dport = wks->udp_dport;
   10105   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10106                 :          0 :                 return;
   10107   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, vxlan_v, vxlan_m, &nic_mask);
             #  #  #  # ]
   10108                 :            :         if ((item->mask == &nic_mask) &&
   10109                 :            :             ((!attr->group && !(attr->transfer && priv->fdb_def_rule) &&
   10110                 :            :             !priv->sh->tunnel_header_0_1) ||
   10111                 :            :             ((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
   10112                 :            :             !priv->sh->misc5_cap)))
   10113                 :            :                 vxlan_m = &rte_flow_item_vxlan_mask;
   10114         [ #  # ]:          0 :         if ((priv->sh->steering_format_version ==
   10115         [ #  # ]:          0 :              MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 &&
   10116                 :          0 :              dport != MLX5_UDP_PORT_VXLAN) ||
   10117   [ #  #  #  #  :          0 :             (!attr->group && !(attr->transfer && priv->fdb_def_rule)) ||
             #  #  #  # ]
   10118   [ #  #  #  # ]:          0 :             ((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
   10119         [ #  # ]:          0 :             !priv->sh->misc5_cap)) {
   10120                 :            :                 misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10121                 :            :                 size = sizeof(vxlan_m->hdr.vni);
   10122                 :          0 :                 vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, vxlan_vni);
   10123         [ #  # ]:          0 :                 for (i = 0; i < size; ++i)
   10124                 :          0 :                         vni_v[i] = vxlan_m->hdr.vni[i] & vxlan_v->hdr.vni[i];
   10125                 :            :                 return;
   10126                 :            :         }
   10127                 :          0 :         tunnel_v = (vxlan_v->hdr.vni[0] & vxlan_m->hdr.vni[0]) |
   10128                 :          0 :                    (vxlan_v->hdr.vni[1] & vxlan_m->hdr.vni[1]) << 8 |
   10129                 :          0 :                    (vxlan_v->hdr.vni[2] & vxlan_m->hdr.vni[2]) << 16;
   10130                 :          0 :         tunnel_v |= (vxlan_v->hdr.rsvd1 & vxlan_m->hdr.rsvd1) << 24;
   10131         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1, RTE_BE32(tunnel_v));
   10132                 :            : }
   10133                 :            : 
   10134                 :            : /**
   10135                 :            :  * Add VXLAN-GPE item to the value.
   10136                 :            :  *
   10137                 :            :  * @param[in, out] key
   10138                 :            :  *   Flow matcher value.
   10139                 :            :  * @param[in] item
   10140                 :            :  *   Flow pattern to translate.
   10141                 :            :  * @param[in] pattern_flags
   10142                 :            :  *   Item pattern flags.
   10143                 :            :  * @param[in] key_type
   10144                 :            :  *   Set flow matcher mask or value.
   10145                 :            :  */
   10146                 :            : 
   10147                 :            : static void
   10148                 :          0 : flow_dv_translate_item_vxlan_gpe(void *key, const struct rte_flow_item *item,
   10149                 :            :                                  const uint64_t pattern_flags,
   10150                 :            :                                  uint32_t key_type)
   10151                 :            : {
   10152                 :            :         static const struct rte_flow_item_vxlan_gpe dummy_vxlan_gpe_hdr = {{{0}}};
   10153                 :          0 :         const struct rte_flow_item_vxlan_gpe *vxlan_m = item->mask;
   10154                 :          0 :         const struct rte_flow_item_vxlan_gpe *vxlan_v = item->spec;
   10155                 :            :         /* The item was validated to be on the outer side */
   10156                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10157                 :            :         void *misc_v =
   10158                 :            :                 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10159                 :          0 :         char *vni_v =
   10160                 :            :                 MLX5_ADDR_OF(fte_match_set_misc3, misc_v, outer_vxlan_gpe_vni);
   10161                 :            :         int i, size = sizeof(vxlan_m->hdr.vni);
   10162                 :            :         uint8_t flags_m = 0xff;
   10163                 :            :         uint8_t flags_v = 0xc;
   10164                 :            :         uint8_t m_protocol, v_protocol;
   10165                 :            : 
   10166   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10167         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10168         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10169                 :            :                                  0xFFFF);
   10170                 :            :                 else
   10171         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10172                 :            :                                  MLX5_UDP_PORT_VXLAN_GPE);
   10173                 :            :         }
   10174         [ #  # ]:          0 :         if (!vxlan_v) {
   10175                 :            :                 vxlan_v = &dummy_vxlan_gpe_hdr;
   10176                 :            :                 vxlan_m = &dummy_vxlan_gpe_hdr;
   10177                 :            :         } else {
   10178         [ #  # ]:          0 :                 if (!vxlan_m)
   10179                 :            :                         vxlan_m = &rte_flow_item_vxlan_gpe_mask;
   10180                 :            :         }
   10181         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10182                 :            :                 vxlan_v = vxlan_m;
   10183         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
   10184                 :            :                 vxlan_m = vxlan_v;
   10185         [ #  # ]:          0 :         if (vxlan_m->hdr.flags) {
   10186                 :            :                 flags_m = vxlan_m->hdr.flags;
   10187                 :          0 :                 flags_v = vxlan_v->hdr.flags;
   10188                 :            :         }
   10189                 :          0 :         m_protocol = vxlan_m->hdr.protocol;
   10190                 :          0 :         v_protocol = vxlan_v->hdr.protocol;
   10191         [ #  # ]:          0 :         if (!m_protocol) {
   10192                 :            :                 /* Force next protocol to ensure next headers parsing. */
   10193         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_NSH)
   10194                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_NSH;
   10195         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L2)
   10196                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_ETH;
   10197         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV4)
   10198                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_IPV4;
   10199         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV6)
   10200                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_IPV6;
   10201         [ #  # ]:          0 :                 if (v_protocol)
   10202                 :            :                         m_protocol = 0xFF;
   10203                 :            :                 /* Restore the value to mask in mask case. */
   10204         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10205                 :            :                         v_protocol = m_protocol;
   10206                 :            :         }
   10207                 :            :         /*
   10208                 :            :          * If only match flags/protocol/vni field, keep using misc3 for matching.
   10209                 :            :          * If need to match rsvd0 or rsvd1, using misc5 and do not need using misc3.
   10210                 :            :          */
   10211   [ #  #  #  #  :          0 :         if (!(vxlan_m->hdr.rsvd0[0] || vxlan_m->hdr.rsvd0[1] || vxlan_m->hdr.rsvd1)) {
                   #  # ]
   10212         [ #  # ]:          0 :                 for (i = 0; i < size; ++i)
   10213                 :          0 :                         vni_v[i] = vxlan_m->hdr.vni[i] & vxlan_v->hdr.vni[i];
   10214         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc_v, outer_vxlan_gpe_flags,
   10215                 :            :                          flags_m & flags_v);
   10216         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc_v,
   10217                 :            :                          outer_vxlan_gpe_next_protocol, m_protocol & v_protocol);
   10218                 :            :         } else {
   10219                 :            :                 uint32_t tunnel_v;
   10220                 :            :                 void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
   10221                 :            : 
   10222                 :          0 :                 tunnel_v = (flags_m & flags_v) << 24 |
   10223                 :          0 :                            (vxlan_v->hdr.rsvd0[0] & vxlan_m->hdr.rsvd0[0]) << 16 |
   10224                 :          0 :                            (vxlan_v->hdr.rsvd0[1] & vxlan_m->hdr.rsvd0[1]) << 8 |
   10225                 :          0 :                            (m_protocol & v_protocol);
   10226         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0, tunnel_v);
   10227                 :          0 :                 tunnel_v = (vxlan_v->hdr.vni[0] & vxlan_m->hdr.vni[0]) << 24 |
   10228                 :          0 :                            (vxlan_v->hdr.vni[1] & vxlan_m->hdr.vni[1]) << 16 |
   10229                 :          0 :                            (vxlan_v->hdr.vni[2] & vxlan_m->hdr.vni[2]) << 8 |
   10230                 :          0 :                            (vxlan_v->hdr.rsvd1 & vxlan_m->hdr.rsvd1);
   10231         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1, tunnel_v);
   10232                 :            :         }
   10233                 :          0 : }
   10234                 :            : 
   10235                 :            : /**
   10236                 :            :  * Add Geneve item to the value.
   10237                 :            :  *
   10238                 :            :  * @param[in, out] key
   10239                 :            :  *   Flow matcher value.
   10240                 :            :  * @param[in] item
   10241                 :            :  *   Flow pattern to translate.
   10242                 :            :  * @param[in] pattern_flags
   10243                 :            :  *   Item pattern flags.
   10244                 :            :  * @param[in] key_type
   10245                 :            :  *   Set flow matcher mask or value.
   10246                 :            :  */
   10247                 :            : 
   10248                 :            : static void
   10249                 :          0 : flow_dv_translate_item_geneve(void *key, const struct rte_flow_item *item,
   10250                 :            :                               uint64_t pattern_flags, uint32_t key_type)
   10251                 :            : {
   10252                 :            :         static const struct rte_flow_item_geneve empty_geneve = {0,};
   10253                 :          0 :         const struct rte_flow_item_geneve *geneve_m = item->mask;
   10254                 :          0 :         const struct rte_flow_item_geneve *geneve_v = item->spec;
   10255                 :            :         /* GENEVE flow item validation allows single tunnel item */
   10256                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10257                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10258                 :            :         uint16_t gbhdr_m;
   10259                 :            :         uint16_t gbhdr_v;
   10260                 :          0 :         char *vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, geneve_vni);
   10261                 :            :         size_t size = sizeof(geneve_m->vni), i;
   10262                 :            :         uint16_t protocol_m, protocol_v;
   10263                 :            : 
   10264   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10265         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10266         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10267                 :            :                                  0xFFFF);
   10268                 :            :                 else
   10269         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10270                 :            :                                  MLX5_UDP_PORT_GENEVE);
   10271                 :            :         }
   10272         [ #  # ]:          0 :         if (!geneve_v) {
   10273                 :            :                 geneve_v = &empty_geneve;
   10274                 :            :                 geneve_m = &empty_geneve;
   10275                 :            :         } else {
   10276         [ #  # ]:          0 :                 if (!geneve_m)
   10277                 :            :                         geneve_m = &rte_flow_item_geneve_mask;
   10278                 :            :         }
   10279         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10280                 :            :                 geneve_v = geneve_m;
   10281         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
   10282                 :            :                 geneve_m = geneve_v;
   10283         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   10284                 :          0 :                 vni_v[i] = geneve_m->vni[i] & geneve_v->vni[i];
   10285         [ #  # ]:          0 :         gbhdr_m = rte_be_to_cpu_16(geneve_m->ver_opt_len_o_c_rsvd0);
   10286         [ #  # ]:          0 :         gbhdr_v = rte_be_to_cpu_16(geneve_v->ver_opt_len_o_c_rsvd0);
   10287         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_oam,
   10288                 :            :                  MLX5_GENEVE_OAMF_VAL(gbhdr_v) & MLX5_GENEVE_OAMF_VAL(gbhdr_m));
   10289         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len,
   10290                 :            :                  MLX5_GENEVE_OPTLEN_VAL(gbhdr_v) &
   10291                 :            :                  MLX5_GENEVE_OPTLEN_VAL(gbhdr_m));
   10292         [ #  # ]:          0 :         protocol_m = rte_be_to_cpu_16(geneve_m->protocol);
   10293         [ #  # ]:          0 :         protocol_v = rte_be_to_cpu_16(geneve_v->protocol);
   10294         [ #  # ]:          0 :         if (!protocol_m) {
   10295                 :            :                 /* Force next protocol to prevent matchers duplication */
   10296                 :            :                 protocol_v = mlx5_translate_tunnel_etypes(pattern_flags);
   10297                 :            :                 if (protocol_v)
   10298                 :            :                         protocol_m = 0xFFFF;
   10299                 :            :                 /* Restore the value to mask in mask case. */
   10300         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10301                 :            :                         protocol_v = protocol_m;
   10302                 :            :         }
   10303         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_protocol_type,
   10304                 :            :                  protocol_m & protocol_v);
   10305                 :          0 : }
   10306                 :            : 
   10307                 :            : /**
   10308                 :            :  * Create Geneve TLV option resource.
   10309                 :            :  *
   10310                 :            :  * @param[in, out] dev
   10311                 :            :  *   Pointer to rte_eth_dev structure.
   10312                 :            :  * @param[in] item
   10313                 :            :  *   Flow pattern to translate.
   10314                 :            :  * @param[out] error
   10315                 :            :  *   pointer to error structure.
   10316                 :            :  *
   10317                 :            :  * @return
   10318                 :            :  *   0 on success otherwise -errno and errno is set.
   10319                 :            :  */
   10320                 :            : static int
   10321                 :          0 : flow_dev_geneve_tlv_option_resource_register(struct rte_eth_dev *dev,
   10322                 :            :                                              const struct rte_flow_item *item,
   10323                 :            :                                              struct rte_flow_error *error)
   10324                 :            : {
   10325                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10326                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   10327                 :          0 :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource =
   10328                 :            :                         sh->geneve_tlv_option_resource;
   10329                 :            :         struct mlx5_devx_obj *obj;
   10330                 :          0 :         const struct rte_flow_item_geneve_opt *geneve_opt_v = item->spec;
   10331                 :            :         int ret = 0;
   10332                 :            : 
   10333                 :            :         MLX5_ASSERT(sh->config.dv_flow_en == 1);
   10334         [ #  # ]:          0 :         if (!geneve_opt_v)
   10335                 :            :                 return -1;
   10336                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
   10337         [ #  # ]:          0 :         if (geneve_opt_resource != NULL) {
   10338                 :          0 :                 if (geneve_opt_resource->option_class ==
   10339                 :            :                         geneve_opt_v->option_class &&
   10340                 :            :                         geneve_opt_resource->option_type ==
   10341         [ #  # ]:          0 :                         geneve_opt_v->option_type &&
   10342                 :            :                         geneve_opt_resource->length ==
   10343                 :            :                         geneve_opt_v->option_len) {
   10344                 :          0 :                         rte_atomic_fetch_add_explicit(&geneve_opt_resource->refcnt, 1,
   10345                 :            :                                            rte_memory_order_relaxed);
   10346                 :            :                 } else {
   10347                 :          0 :                         ret = rte_flow_error_set(error, ENOMEM,
   10348                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10349                 :            :                                 "Only one GENEVE TLV option supported");
   10350                 :          0 :                         goto exit;
   10351                 :            :                 }
   10352                 :            :         } else {
   10353                 :          0 :                 struct mlx5_devx_geneve_tlv_option_attr attr = {
   10354                 :          0 :                         .option_class = geneve_opt_v->option_class,
   10355                 :          0 :                         .option_type = geneve_opt_v->option_type,
   10356                 :          0 :                         .option_data_len = geneve_opt_v->option_len,
   10357                 :            :                 };
   10358                 :            : 
   10359                 :            :                 /* Create a GENEVE TLV object and resource. */
   10360                 :          0 :                 obj = mlx5_devx_cmd_create_geneve_tlv_option(sh->cdev->ctx,
   10361                 :            :                                                              &attr);
   10362         [ #  # ]:          0 :                 if (!obj) {
   10363                 :          0 :                         ret = rte_flow_error_set(error, ENODATA,
   10364                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10365                 :            :                                 "Failed to create GENEVE TLV Devx object");
   10366                 :          0 :                         goto exit;
   10367                 :            :                 }
   10368                 :          0 :                 sh->geneve_tlv_option_resource =
   10369                 :          0 :                                 mlx5_malloc(MLX5_MEM_ZERO,
   10370                 :            :                                                 sizeof(*geneve_opt_resource),
   10371                 :            :                                                 0, SOCKET_ID_ANY);
   10372         [ #  # ]:          0 :                 if (!sh->geneve_tlv_option_resource) {
   10373                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy(obj));
   10374                 :          0 :                         ret = rte_flow_error_set(error, ENOMEM,
   10375                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10376                 :            :                                 "GENEVE TLV object memory allocation failed");
   10377                 :          0 :                         goto exit;
   10378                 :            :                 }
   10379                 :            :                 geneve_opt_resource = sh->geneve_tlv_option_resource;
   10380                 :          0 :                 geneve_opt_resource->obj = obj;
   10381                 :          0 :                 geneve_opt_resource->option_class = geneve_opt_v->option_class;
   10382                 :          0 :                 geneve_opt_resource->option_type = geneve_opt_v->option_type;
   10383                 :          0 :                 geneve_opt_resource->length = geneve_opt_v->option_len;
   10384                 :          0 :                 rte_atomic_store_explicit(&geneve_opt_resource->refcnt, 1,
   10385                 :            :                                 rte_memory_order_relaxed);
   10386                 :            :         }
   10387                 :          0 : exit:
   10388                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
   10389                 :          0 :         return ret;
   10390                 :            : }
   10391                 :            : 
   10392                 :            : /**
   10393                 :            :  * Add Geneve TLV option item to value.
   10394                 :            :  *
   10395                 :            :  * @param[in, out] dev
   10396                 :            :  *   Pointer to rte_eth_dev structure.
   10397                 :            :  * @param[in, out] key
   10398                 :            :  *   Flow matcher value.
   10399                 :            :  * @param[in] item
   10400                 :            :  *   Flow pattern to translate.
   10401                 :            :  * @param[in] key_type
   10402                 :            :  *   Set flow matcher mask or value.
   10403                 :            :  * @param[out] error
   10404                 :            :  *   Pointer to error structure.
   10405                 :            :  */
   10406                 :            : static int
   10407                 :          0 : flow_dv_translate_item_geneve_opt(struct rte_eth_dev *dev, void *key,
   10408                 :            :                                   const struct rte_flow_item *item,
   10409                 :            :                                   uint32_t key_type,
   10410                 :            :                                   struct rte_flow_error *error)
   10411                 :            : {
   10412                 :            :         const struct rte_flow_item_geneve_opt *geneve_opt_m;
   10413                 :            :         const struct rte_flow_item_geneve_opt *geneve_opt_v;
   10414                 :          0 :         const struct rte_flow_item_geneve_opt *orig_spec = item->spec;
   10415                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10416                 :          0 :         rte_be32_t opt_data_key = 0, opt_data_mask = 0;
   10417                 :            :         size_t option_byte_len;
   10418                 :            :         int ret = 0;
   10419                 :            : 
   10420   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type) || !orig_spec)
          #  #  #  #  #  
                #  #  # ]
   10421                 :            :                 return -1;
   10422   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, geneve_opt_v, geneve_opt_m,
             #  #  #  # ]
   10423                 :            :                          &rte_flow_item_geneve_opt_mask);
   10424                 :            :         /*
   10425                 :            :          * Register resource requires item spec for SW steering,
   10426                 :            :          * for HW steering resources is registered explicitly by user.
   10427                 :            :          */
   10428         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW_V) {
   10429                 :          0 :                 ret = flow_dev_geneve_tlv_option_resource_register(dev, item,
   10430                 :            :                                                                    error);
   10431         [ #  # ]:          0 :                 if (ret) {
   10432                 :          0 :                         DRV_LOG(ERR, "Failed to create geneve_tlv_obj");
   10433                 :          0 :                         return ret;
   10434                 :            :                 }
   10435                 :            :         }
   10436                 :            :         /* Convert the option length from DW to bytes for using memcpy. */
   10437                 :          0 :         option_byte_len = RTE_MIN((size_t)(orig_spec->option_len * 4),
   10438                 :            :                                   sizeof(rte_be32_t));
   10439         [ #  # ]:          0 :         if (geneve_opt_v->data) {
   10440                 :            :                 memcpy(&opt_data_key, geneve_opt_v->data, option_byte_len);
   10441                 :          0 :                 memcpy(&opt_data_mask, geneve_opt_m->data, option_byte_len);
   10442   [ #  #  #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v,
   10443                 :            :                          geneve_tlv_option_0_data,
   10444                 :            :                          rte_be_to_cpu_32(opt_data_key & opt_data_mask));
   10445                 :            :         }
   10446                 :            :         return ret;
   10447                 :            : }
   10448                 :            : 
   10449                 :            : /**
   10450                 :            :  * Add MPLS item to the value.
   10451                 :            :  *
   10452                 :            :  * @param[in, out] key
   10453                 :            :  *   Flow matcher value.
   10454                 :            :  * @param[in] item
   10455                 :            :  *   Flow pattern to translate.
   10456                 :            :  * @param[in] prev_layer
   10457                 :            :  *   The protocol layer indicated in previous item.
   10458                 :            :  * @param[in] inner
   10459                 :            :  *   Item is inner pattern.
   10460                 :            :  * @param[in] key_type
   10461                 :            :  *   Set flow matcher mask or value.
   10462                 :            :  */
   10463                 :            : static void
   10464                 :          0 : flow_dv_translate_item_mpls(void *key, const struct rte_flow_item *item,
   10465                 :            :                             uint64_t prev_layer, int inner,
   10466                 :            :                             uint32_t key_type)
   10467                 :            : {
   10468                 :            :         const uint32_t *in_mpls_m;
   10469                 :            :         const uint32_t *in_mpls_v;
   10470                 :            :         uint32_t *out_mpls_v = 0;
   10471                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10472                 :          0 :         void *misc2_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
   10473                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10474                 :            : 
   10475      [ #  #  # ]:          0 :         switch (prev_layer) {
   10476                 :          0 :         case MLX5_FLOW_LAYER_OUTER_L4_UDP:
   10477   [ #  #  #  # ]:          0 :                 if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10478         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10479         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10480                 :            :                                          udp_dport, 0xffff);
   10481                 :            :                         else
   10482         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10483                 :            :                                          udp_dport, MLX5_UDP_PORT_MPLS);
   10484                 :            :                 }
   10485                 :            :                 break;
   10486                 :          0 :         case MLX5_FLOW_LAYER_GRE:
   10487                 :            :                 /* Fall-through. */
   10488                 :            :         case MLX5_FLOW_LAYER_GRE_KEY:
   10489   [ #  #  #  # ]:          0 :                 if (!MLX5_GET16(fte_match_set_misc, misc_v, gre_protocol)) {
   10490         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10491         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_misc, misc_v,
   10492                 :            :                                          gre_protocol, 0xffff);
   10493                 :            :                         else
   10494         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_misc, misc_v,
   10495                 :            :                                          gre_protocol, RTE_ETHER_TYPE_MPLS);
   10496                 :            :                 }
   10497                 :            :                 break;
   10498                 :            :         default:
   10499                 :            :                 break;
   10500                 :            :         }
   10501   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10502                 :            :                 return;
   10503   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, in_mpls_v, in_mpls_m,
             #  #  #  # ]
   10504                 :            :                          &rte_flow_item_mpls_mask);
   10505      [ #  #  # ]:          0 :         switch (prev_layer) {
   10506                 :          0 :         case MLX5_FLOW_LAYER_OUTER_L4_UDP:
   10507                 :          0 :                 out_mpls_v =
   10508                 :            :                         (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
   10509                 :            :                                                  outer_first_mpls_over_udp);
   10510                 :          0 :                 break;
   10511                 :          0 :         case MLX5_FLOW_LAYER_GRE:
   10512                 :          0 :                 out_mpls_v =
   10513                 :            :                         (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
   10514                 :            :                                                  outer_first_mpls_over_gre);
   10515                 :          0 :                 break;
   10516                 :          0 :         default:
   10517                 :            :                 /* Inner MPLS not over GRE is not supported. */
   10518         [ #  # ]:          0 :                 if (!inner)
   10519                 :            :                         out_mpls_v =
   10520                 :            :                                 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2,
   10521                 :            :                                                          misc2_v,
   10522                 :            :                                                          outer_first_mpls);
   10523                 :            :                 break;
   10524                 :            :         }
   10525                 :            :         if (out_mpls_v)
   10526                 :          0 :                 *out_mpls_v = *in_mpls_v & *in_mpls_m;
   10527                 :            : }
   10528                 :            : 
   10529                 :            : /**
   10530                 :            :  * Add metadata register item to matcher
   10531                 :            :  *
   10532                 :            :  * @param[in, out] key
   10533                 :            :  *   Flow matcher value.
   10534                 :            :  * @param[in] reg_type
   10535                 :            :  *   Type of device metadata register
   10536                 :            :  * @param[in] data
   10537                 :            :  *   Register data
   10538                 :            :  * @param[in] mask
   10539                 :            :  *   Register mask
   10540                 :            :  */
   10541                 :            : static void
   10542                 :          0 : flow_dv_match_meta_reg(void *key, enum modify_reg reg_type,
   10543                 :            :                        uint32_t data, uint32_t mask)
   10544                 :            : {
   10545                 :            :         void *misc2_v =
   10546                 :            :                 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
   10547                 :            :         uint32_t temp;
   10548                 :            : 
   10549         [ #  # ]:          0 :         if (!key)
   10550                 :            :                 return;
   10551                 :          0 :         data &= mask;
   10552   [ #  #  #  #  :          0 :         switch (reg_type) {
          #  #  #  #  #  
                   #  # ]
   10553                 :          0 :         case REG_A:
   10554         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_a, data);
   10555                 :          0 :                 break;
   10556                 :          0 :         case REG_B:
   10557         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_b, data);
   10558                 :          0 :                 break;
   10559                 :          0 :         case REG_C_0:
   10560                 :            :                 /*
   10561                 :            :                  * The metadata register C0 field might be divided into
   10562                 :            :                  * source vport index and META item value, we should set
   10563                 :            :                  * this field according to specified mask, not as whole one.
   10564                 :            :                  */
   10565         [ #  # ]:          0 :                 temp = MLX5_GET(fte_match_set_misc2, misc2_v, metadata_reg_c_0);
   10566         [ #  # ]:          0 :                 if (mask)
   10567                 :          0 :                         temp &= ~mask;
   10568                 :          0 :                 temp |= data;
   10569         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, temp);
   10570                 :          0 :                 break;
   10571                 :          0 :         case REG_C_1:
   10572         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_1, data);
   10573                 :          0 :                 break;
   10574                 :          0 :         case REG_C_2:
   10575         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_2, data);
   10576                 :          0 :                 break;
   10577                 :          0 :         case REG_C_3:
   10578         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_3, data);
   10579                 :          0 :                 break;
   10580                 :          0 :         case REG_C_4:
   10581         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_4, data);
   10582                 :          0 :                 break;
   10583                 :          0 :         case REG_C_5:
   10584         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_5, data);
   10585                 :          0 :                 break;
   10586                 :          0 :         case REG_C_6:
   10587         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_6, data);
   10588                 :          0 :                 break;
   10589                 :          0 :         case REG_C_7:
   10590         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_7, data);
   10591                 :          0 :                 break;
   10592                 :            :         default:
   10593                 :            :                 MLX5_ASSERT(false);
   10594                 :            :                 break;
   10595                 :            :         }
   10596                 :            : }
   10597                 :            : 
   10598                 :            : /**
   10599                 :            :  * Add metadata register item to matcher
   10600                 :            :  *
   10601                 :            :  * @param[in, out] matcher
   10602                 :            :  *   Flow matcher.
   10603                 :            :  * @param[in, out] key
   10604                 :            :  *   Flow matcher value.
   10605                 :            :  * @param[in] reg_type
   10606                 :            :  *   Type of device metadata register
   10607                 :            :  * @param[in] value
   10608                 :            :  *   Register value
   10609                 :            :  * @param[in] mask
   10610                 :            :  *   Register mask
   10611                 :            :  */
   10612                 :            : static void
   10613                 :            : flow_dv_match_meta_reg_all(void *matcher, void *key, enum modify_reg reg_type,
   10614                 :            :                            uint32_t data, uint32_t mask)
   10615                 :            : {
   10616                 :          0 :         flow_dv_match_meta_reg(key, reg_type, data, mask);
   10617                 :          0 :         flow_dv_match_meta_reg(matcher, reg_type, mask, mask);
   10618                 :            : }
   10619                 :            : 
   10620                 :            : /**
   10621                 :            :  * Add MARK item to matcher
   10622                 :            :  *
   10623                 :            :  * @param[in] dev
   10624                 :            :  *   The device to configure through.
   10625                 :            :  * @param[in, out] key
   10626                 :            :  *   Flow matcher value.
   10627                 :            :  * @param[in] item
   10628                 :            :  *   Flow pattern to translate.
   10629                 :            :  * @param[in] key_type
   10630                 :            :  *   Set flow matcher mask or value.
   10631                 :            :  */
   10632                 :            : static void
   10633                 :          0 : flow_dv_translate_item_mark(struct rte_eth_dev *dev, void *key,
   10634                 :            :                             const struct rte_flow_item *item,
   10635                 :            :                             uint32_t key_type)
   10636                 :            : {
   10637                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10638                 :            :         const struct rte_flow_item_mark *mark;
   10639                 :            :         uint32_t value;
   10640                 :            :         uint32_t mask = 0;
   10641                 :            : 
   10642         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW) {
   10643         [ #  # ]:          0 :                 mark = item->mask ? (const void *)item->mask :
   10644                 :            :                                     &rte_flow_item_mark_mask;
   10645                 :          0 :                 mask = mark->id;
   10646         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M) {
   10647                 :            :                         value = mask;
   10648                 :            :                 } else {
   10649                 :          0 :                         mark = (const void *)item->spec;
   10650                 :            :                         MLX5_ASSERT(mark);
   10651                 :          0 :                         value = mark->id;
   10652                 :            :                 }
   10653                 :            :         } else {
   10654         [ #  # ]:          0 :                 mark = (key_type == MLX5_SET_MATCHER_HS_V) ?
   10655                 :            :                         (const void *)item->spec : (const void *)item->mask;
   10656                 :            :                 MLX5_ASSERT(mark);
   10657                 :          0 :                 value = mark->id;
   10658         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_HS_M)
   10659                 :            :                         mask = value;
   10660                 :            :         }
   10661                 :          0 :         mask &= priv->sh->dv_mark_mask;
   10662                 :          0 :         value &= mask;
   10663         [ #  # ]:          0 :         if (mask) {
   10664                 :            :                 enum modify_reg reg;
   10665                 :            : 
   10666                 :            :                 /* Get the metadata register index for the mark. */
   10667                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, NULL);
   10668                 :            :                 MLX5_ASSERT(reg > 0);
   10669         [ #  # ]:          0 :                 if (reg == REG_C_0) {
   10670                 :          0 :                         struct mlx5_priv *priv = dev->data->dev_private;
   10671                 :          0 :                         uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10672                 :            :                         uint32_t shl_c0 = rte_bsf32(msk_c0);
   10673                 :            : 
   10674                 :          0 :                         mask &= msk_c0;
   10675                 :          0 :                         mask <<= shl_c0;
   10676                 :          0 :                         value <<= shl_c0;
   10677                 :            :                 }
   10678                 :          0 :                 flow_dv_match_meta_reg(key, reg, value, mask);
   10679                 :            :         }
   10680                 :          0 : }
   10681                 :            : 
   10682                 :            : /**
   10683                 :            :  * Add META item to matcher
   10684                 :            :  *
   10685                 :            :  * @param[in] dev
   10686                 :            :  *   The devich to configure through.
   10687                 :            :  * @param[in, out] key
   10688                 :            :  *   Flow matcher value.
   10689                 :            :  * @param[in] attr
   10690                 :            :  *   Attributes of flow that includes this item.
   10691                 :            :  * @param[in] item
   10692                 :            :  *   Flow pattern to translate.
   10693                 :            :  * @param[in] key_type
   10694                 :            :  *   Set flow matcher mask or value.
   10695                 :            :  */
   10696                 :            : static void
   10697                 :          0 : flow_dv_translate_item_meta(struct rte_eth_dev *dev,
   10698                 :            :                             void *key,
   10699                 :            :                             const struct rte_flow_attr *attr,
   10700                 :            :                             const struct rte_flow_item *item,
   10701                 :            :                             uint32_t key_type)
   10702                 :            : {
   10703                 :            :         const struct rte_flow_item_meta *meta_m;
   10704                 :            :         const struct rte_flow_item_meta *meta_v;
   10705                 :            :         uint32_t value;
   10706                 :            :         uint32_t mask = 0;
   10707                 :            :         int reg;
   10708                 :            : 
   10709   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10710                 :            :                 return;
   10711   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, meta_v, meta_m,
             #  #  #  # ]
   10712                 :            :                          &rte_flow_item_meta_mask);
   10713                 :          0 :         value = meta_v->data;
   10714                 :          0 :         mask = meta_m->data;
   10715         [ #  # ]:          0 :         if (key_type == MLX5_SET_MATCHER_HS_M)
   10716                 :            :                 mask = value;
   10717                 :            :         /*
   10718                 :            :          * In the current implementation, REG_B cannot be used to match.
   10719                 :            :          * Force to use REG_C_1 in HWS root table as other tables.
   10720                 :            :          * This map may change.
   10721                 :            :          * NIC: modify - REG_B to be present in SW
   10722                 :            :          *      match - REG_C_1 when copied from FDB, different from SWS
   10723                 :            :          * FDB: modify - REG_C_1 in Xmeta mode, REG_NON in legacy mode
   10724                 :            :          *      match - REG_C_1 in FDB
   10725                 :            :          */
   10726         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   10727                 :          0 :                 reg = flow_dv_get_metadata_reg(dev, attr, NULL);
   10728                 :            :         else
   10729                 :            :                 reg = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_META, 0);
   10730         [ #  # ]:          0 :         if (reg < 0)
   10731                 :            :                 return;
   10732                 :            :         MLX5_ASSERT(reg != REG_NON);
   10733         [ #  # ]:          0 :         if (reg == REG_C_0) {
   10734                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
   10735                 :          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10736                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
   10737                 :            : 
   10738                 :          0 :                 mask &= msk_c0;
   10739                 :          0 :                 mask <<= shl_c0;
   10740                 :          0 :                 value <<= shl_c0;
   10741                 :            :         }
   10742                 :          0 :         flow_dv_match_meta_reg(key, reg, value, mask);
   10743                 :            : }
   10744                 :            : 
   10745                 :            : /**
   10746                 :            :  * Add vport metadata Reg C0 item to matcher
   10747                 :            :  *
   10748                 :            :  * @param[in, out] key
   10749                 :            :  *   Flow matcher value.
   10750                 :            :  * @param[in] value
   10751                 :            :  *   Register value
   10752                 :            :  * @param[in] mask
   10753                 :            :  *   Register mask
   10754                 :            :  */
   10755                 :            : static void
   10756                 :            : flow_dv_translate_item_meta_vport(void *key, uint32_t value, uint32_t mask)
   10757                 :            : {
   10758                 :          0 :         flow_dv_match_meta_reg(key, REG_C_0, value, mask);
   10759                 :          0 : }
   10760                 :            : 
   10761                 :            : /**
   10762                 :            :  * Add tag item to matcher
   10763                 :            :  *
   10764                 :            :  * @param[in] dev
   10765                 :            :  *   The devich to configure through.
   10766                 :            :  * @param[in, out] key
   10767                 :            :  *   Flow matcher value.
   10768                 :            :  * @param[in] item
   10769                 :            :  *   Flow pattern to translate.
   10770                 :            :  * @param[in] key_type
   10771                 :            :  *   Set flow matcher mask or value.
   10772                 :            :  */
   10773                 :            : static void
   10774                 :          0 : flow_dv_translate_mlx5_item_tag(struct rte_eth_dev *dev, void *key,
   10775                 :            :                                 const struct rte_flow_item *item,
   10776                 :            :                                 uint32_t key_type)
   10777                 :            : {
   10778                 :          0 :         const struct mlx5_rte_flow_item_tag *tag_v = item->spec;
   10779                 :          0 :         const struct mlx5_rte_flow_item_tag *tag_m = item->mask;
   10780                 :            :         uint32_t mask, value;
   10781                 :            : 
   10782                 :            :         MLX5_ASSERT(tag_v);
   10783                 :          0 :         value = tag_v->data;
   10784         [ #  # ]:          0 :         mask = tag_m ? tag_m->data : UINT32_MAX;
   10785         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10786                 :            :                 value = mask;
   10787         [ #  # ]:          0 :         if (tag_v->id == REG_C_0) {
   10788                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
   10789                 :          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10790                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
   10791                 :            : 
   10792                 :          0 :                 mask &= msk_c0;
   10793                 :          0 :                 mask <<= shl_c0;
   10794                 :          0 :                 value <<= shl_c0;
   10795                 :            :         }
   10796                 :          0 :         flow_dv_match_meta_reg(key, tag_v->id, value, mask);
   10797                 :          0 : }
   10798                 :            : 
   10799                 :            : /**
   10800                 :            :  * Add TAG item to matcher
   10801                 :            :  *
   10802                 :            :  * @param[in] dev
   10803                 :            :  *   The devich to configure through.
   10804                 :            :  * @param[in, out] key
   10805                 :            :  *   Flow matcher value.
   10806                 :            :  * @param[in] item
   10807                 :            :  *   Flow pattern to translate.
   10808                 :            :  * @param[in] key_type
   10809                 :            :  *   Set flow matcher mask or value.
   10810                 :            :  */
   10811                 :            : static void
   10812                 :          0 : flow_dv_translate_item_tag(struct rte_eth_dev *dev, void *key,
   10813                 :            :                            const struct rte_flow_item *item,
   10814                 :            :                            uint32_t key_type)
   10815                 :            : {
   10816                 :          0 :         const struct rte_flow_item_tag *tag_vv = item->spec;
   10817                 :            :         const struct rte_flow_item_tag *tag_v;
   10818                 :            :         const struct rte_flow_item_tag *tag_m;
   10819                 :            :         int reg;
   10820                 :            :         uint32_t index;
   10821                 :            : 
   10822   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10823                 :            :                 return;
   10824   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, tag_v, tag_m,
             #  #  #  # ]
   10825                 :            :                 &rte_flow_item_tag_mask);
   10826                 :            :         /* When set mask, the index should be from spec. */
   10827         [ #  # ]:          0 :         index = tag_vv ? tag_vv->index : tag_v->index;
   10828                 :            :         /* Get the metadata register index for the tag. */
   10829         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   10830                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, index, NULL);
   10831                 :            :         else
   10832                 :            :                 reg = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_TAG, index);
   10833                 :            :         MLX5_ASSERT(reg > 0);
   10834                 :          0 :         flow_dv_match_meta_reg(key, (enum modify_reg)reg, tag_v->data, tag_m->data);
   10835                 :            : }
   10836                 :            : 
   10837                 :            : /**
   10838                 :            :  * Add source vport match to the specified matcher.
   10839                 :            :  *
   10840                 :            :  * @param[in, out] key
   10841                 :            :  *   Flow matcher value.
   10842                 :            :  * @param[in] port
   10843                 :            :  *   Source vport value to match
   10844                 :            :  */
   10845                 :            : static void
   10846                 :            : flow_dv_translate_item_source_vport(void *key,
   10847                 :            :                                     int16_t port)
   10848                 :            : {
   10849                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10850                 :            : 
   10851   [ #  #  #  #  :          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_port, port);
                   #  # ]
   10852                 :          0 : }
   10853                 :            : 
   10854                 :            : /**
   10855                 :            :  * Translate port-id item to eswitch match on  port-id.
   10856                 :            :  *
   10857                 :            :  * @param[in] dev
   10858                 :            :  *   The devich to configure through.
   10859                 :            :  * @param[in, out] key
   10860                 :            :  *   Flow matcher value.
   10861                 :            :  * @param[in] item
   10862                 :            :  *   Flow pattern to translate.
   10863                 :            :  * @param[in] attr
   10864                 :            :  *   Flow attributes.
   10865                 :            :  * @param[in] key_type
   10866                 :            :  *   Set flow matcher mask or value.
   10867                 :            :  *
   10868                 :            :  * @return
   10869                 :            :  *   0 on success, a negative errno value otherwise.
   10870                 :            :  */
   10871                 :            : static int
   10872                 :          0 : flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *key,
   10873                 :            :                                const struct rte_flow_item *item,
   10874                 :            :                                const struct rte_flow_attr *attr,
   10875                 :            :                                uint32_t key_type)
   10876                 :            : {
   10877         [ #  # ]:          0 :         const struct rte_flow_item_port_id *pid_m = item ? item->mask : NULL;
   10878         [ #  # ]:          0 :         const struct rte_flow_item_port_id *pid_v = item ? item->spec : NULL;
   10879                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   10880                 :            :         struct mlx5_priv *priv;
   10881                 :            :         uint16_t mask, id;
   10882                 :            :         uint32_t vport_meta;
   10883                 :            : 
   10884                 :            :         MLX5_ASSERT(wks);
   10885   [ #  #  #  # ]:          0 :         if (pid_v && pid_v->id == MLX5_PORT_ESW_MGR) {
   10886                 :          0 :                 flow_dv_translate_item_source_vport(key,
   10887         [ #  # ]:          0 :                                 key_type & MLX5_SET_MATCHER_V ?
   10888                 :          0 :                                 mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10889                 :          0 :                 return 0;
   10890                 :            :         }
   10891         [ #  # ]:          0 :         mask = pid_m ? pid_m->id : 0xffff;
   10892         [ #  # ]:          0 :         id = pid_v ? pid_v->id : dev->data->port_id;
   10893                 :          0 :         priv = mlx5_port_to_eswitch_info(id, item == NULL);
   10894         [ #  # ]:          0 :         if (!priv)
   10895                 :          0 :                 return -rte_errno;
   10896         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   10897                 :            :                 id = mask;
   10898                 :          0 :                 vport_meta = priv->vport_meta_mask;
   10899                 :            :         } else {
   10900                 :          0 :                 id = priv->vport_id;
   10901                 :          0 :                 vport_meta = priv->vport_meta_tag;
   10902                 :          0 :                 wks->vport_meta_tag = vport_meta;
   10903                 :            :         }
   10904                 :            :         /*
   10905                 :            :          * Translate to vport field or to metadata, depending on mode.
   10906                 :            :          * Kernel can use either misc.source_port or half of C0 metadata
   10907                 :            :          * register.
   10908                 :            :          */
   10909         [ #  # ]:          0 :         if (priv->vport_meta_mask) {
   10910                 :            :                 /*
   10911                 :            :                  * Provide the hint for SW steering library
   10912                 :            :                  * to insert the flow into ingress domain and
   10913                 :            :                  * save the extra vport match.
   10914                 :            :                  */
   10915   [ #  #  #  # ]:          0 :                 if (mask == 0xffff && priv->vport_id == 0xffff &&
   10916   [ #  #  #  # ]:          0 :                     priv->pf_bond < 0 && attr->transfer)
   10917         [ #  # ]:          0 :                         flow_dv_translate_item_source_vport(key, id);
   10918                 :            :                 /*
   10919                 :            :                  * We should always set the vport metadata register,
   10920                 :            :                  * otherwise the SW steering library can drop
   10921                 :            :                  * the rule if wire vport metadata value is not zero,
   10922                 :            :                  * it depends on kernel configuration.
   10923                 :            :                  */
   10924                 :          0 :                 flow_dv_translate_item_meta_vport
   10925                 :            :                                 (key, vport_meta, priv->vport_meta_mask);
   10926                 :            :         } else {
   10927         [ #  # ]:          0 :                 flow_dv_translate_item_source_vport(key, id);
   10928                 :            :         }
   10929                 :            :         return 0;
   10930                 :            : }
   10931                 :            : 
   10932                 :            : /**
   10933                 :            :  * Translate port representor item to eswitch match on port id.
   10934                 :            :  *
   10935                 :            :  * @param[in] dev
   10936                 :            :  *   The devich to configure through.
   10937                 :            :  * @param[in, out] key
   10938                 :            :  *   Flow matcher value.
   10939                 :            :  * @param[in] key_type
   10940                 :            :  *   Set flow matcher mask or value.
   10941                 :            :  *
   10942                 :            :  * @return
   10943                 :            :  *   0 on success, a negative errno value otherwise.
   10944                 :            :  */
   10945                 :            : static int
   10946                 :          0 : flow_dv_translate_item_port_representor(struct rte_eth_dev *dev, void *key,
   10947                 :            :                                         uint32_t key_type)
   10948                 :            : {
   10949                 :          0 :         flow_dv_translate_item_source_vport(key,
   10950         [ #  # ]:          0 :                         key_type & MLX5_SET_MATCHER_V ?
   10951                 :          0 :                         mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10952                 :          0 :         return 0;
   10953                 :            : }
   10954                 :            : 
   10955                 :            : /**
   10956                 :            :  * Translate represented port item to eswitch match on port id.
   10957                 :            :  *
   10958                 :            :  * @param[in] dev
   10959                 :            :  *   The devich to configure through.
   10960                 :            :  * @param[in, out] key
   10961                 :            :  *   Flow matcher value.
   10962                 :            :  * @param[in] item
   10963                 :            :  *   Flow pattern to translate.
   10964                 :            :  * @param[in]
   10965                 :            :  *   Flow attributes.
   10966                 :            :  *
   10967                 :            :  * @return
   10968                 :            :  *   0 on success, a negative errno value otherwise.
   10969                 :            :  */
   10970                 :            : static int
   10971                 :          0 : flow_dv_translate_item_represented_port(struct rte_eth_dev *dev, void *key,
   10972                 :            :                                         const struct rte_flow_item *item,
   10973                 :            :                                         const struct rte_flow_attr *attr,
   10974                 :            :                                         uint32_t key_type)
   10975                 :            : {
   10976         [ #  # ]:          0 :         const struct rte_flow_item_ethdev *pid_m = item ? item->mask : NULL;
   10977         [ #  # ]:          0 :         const struct rte_flow_item_ethdev *pid_v = item ? item->spec : NULL;
   10978                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   10979                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10980                 :            :         uint16_t mask, id;
   10981                 :            :         uint32_t vport_meta;
   10982                 :            :         bool vport_match = false;
   10983                 :            : 
   10984                 :            :         MLX5_ASSERT(wks);
   10985                 :            : #ifndef HAVE_IBV_DEVICE_ATTR_ESW_MGR_REG_C0
   10986         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
   10987                 :            :                 vport_match = true;
   10988                 :            : #endif
   10989         [ #  # ]:          0 :         if (!pid_m && !pid_v)
   10990                 :            :                 return 0;
   10991   [ #  #  #  # ]:          0 :         if (pid_v && pid_v->port_id == UINT16_MAX) {
   10992   [ #  #  #  # ]:          0 :                 if (priv->sh->config.dv_flow_en != 2 || vport_match) {
   10993                 :          0 :                         flow_dv_translate_item_source_vport
   10994         [ #  # ]:          0 :                                 (key, key_type & MLX5_SET_MATCHER_V ?
   10995                 :          0 :                                  mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10996                 :            :                 } else {
   10997         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10998                 :          0 :                                 vport_meta = priv->sh->dev_cap.esw_info.regc_mask;
   10999                 :            :                         else
   11000                 :          0 :                                 vport_meta = priv->sh->dev_cap.esw_info.regc_value;
   11001                 :          0 :                         flow_dv_translate_item_meta_vport(key, vport_meta,
   11002                 :            :                                                           priv->sh->dev_cap.esw_info.regc_mask);
   11003                 :            :                 }
   11004                 :          0 :                 return 0;
   11005                 :            :         }
   11006         [ #  # ]:          0 :         mask = pid_m ? pid_m->port_id : UINT16_MAX;
   11007         [ #  # ]:          0 :         id = pid_v ? pid_v->port_id : dev->data->port_id;
   11008                 :          0 :         priv = mlx5_port_to_eswitch_info(id, item == NULL);
   11009         [ #  # ]:          0 :         if (!priv)
   11010                 :          0 :                 return -rte_errno;
   11011         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   11012                 :            :                 id = mask;
   11013                 :          0 :                 vport_meta = priv->vport_meta_mask;
   11014                 :            :         } else {
   11015                 :          0 :                 id = priv->vport_id;
   11016                 :          0 :                 vport_meta = priv->vport_meta_tag;
   11017                 :          0 :                 wks->vport_meta_tag = vport_meta;
   11018                 :            :         }
   11019                 :            :         /*
   11020                 :            :          * Translate to vport field or to metadata, depending on mode.
   11021                 :            :          * Kernel can use either misc.source_port or half of C0 metadata
   11022                 :            :          * register.
   11023                 :            :          */
   11024   [ #  #  #  # ]:          0 :         if (priv->vport_meta_mask && !vport_match) {
   11025                 :            :                 /*
   11026                 :            :                  * Provide the hint for SW steering library
   11027                 :            :                  * to insert the flow into ingress domain and
   11028                 :            :                  * save the extra vport match.
   11029                 :            :                  */
   11030   [ #  #  #  # ]:          0 :                 if (mask == UINT16_MAX && priv->vport_id == UINT16_MAX &&
   11031   [ #  #  #  # ]:          0 :                     priv->pf_bond < 0 && attr->transfer &&
   11032         [ #  # ]:          0 :                     priv->sh->config.dv_flow_en != 2)
   11033         [ #  # ]:          0 :                         flow_dv_translate_item_source_vport(key, id);
   11034                 :            :                 /*
   11035                 :            :                  * We should always set the vport metadata register,
   11036                 :            :                  * otherwise the SW steering library can drop
   11037                 :            :                  * the rule if wire vport metadata value is not zero,
   11038                 :            :                  * it depends on kernel configuration.
   11039                 :            :                  */
   11040                 :          0 :                 flow_dv_translate_item_meta_vport(key, vport_meta,
   11041                 :            :                                                   priv->vport_meta_mask);
   11042                 :            :         } else {
   11043         [ #  # ]:          0 :                 flow_dv_translate_item_source_vport(key, id);
   11044                 :            :         }
   11045                 :            :         return 0;
   11046                 :            : }
   11047                 :            : 
   11048                 :            : /**
   11049                 :            :  * Translate port-id item to eswitch match on  port-id.
   11050                 :            :  *
   11051                 :            :  * @param[in] dev
   11052                 :            :  *   The devich to configure through.
   11053                 :            :  * @param[in, out] matcher
   11054                 :            :  *   Flow matcher.
   11055                 :            :  * @param[in, out] key
   11056                 :            :  *   Flow matcher value.
   11057                 :            :  * @param[in] item
   11058                 :            :  *   Flow pattern to translate.
   11059                 :            :  * @param[in] attr
   11060                 :            :  *   Flow attributes.
   11061                 :            :  *
   11062                 :            :  * @return
   11063                 :            :  *   0 on success, a negative errno value otherwise.
   11064                 :            :  */
   11065                 :            : static int
   11066                 :          0 : flow_dv_translate_item_port_id_all(struct rte_eth_dev *dev,
   11067                 :            :                                void *matcher, void *key,
   11068                 :            :                                const struct rte_flow_item *item,
   11069                 :            :                                const struct rte_flow_attr *attr)
   11070                 :            : {
   11071                 :            :         int ret;
   11072                 :            : 
   11073                 :          0 :         ret = flow_dv_translate_item_port_id
   11074                 :            :                         (dev, matcher, item, attr, MLX5_SET_MATCHER_SW_M);
   11075         [ #  # ]:          0 :         if (ret)
   11076                 :            :                 return ret;
   11077                 :          0 :         ret = flow_dv_translate_item_port_id
   11078                 :            :                         (dev, key, item, attr, MLX5_SET_MATCHER_SW_V);
   11079                 :          0 :         return ret;
   11080                 :            : }
   11081                 :            : 
   11082                 :            : 
   11083                 :            : /**
   11084                 :            :  * Add ICMP6 item to the value.
   11085                 :            :  *
   11086                 :            :  * @param[in, out] key
   11087                 :            :  *   Flow matcher value.
   11088                 :            :  * @param[in] item
   11089                 :            :  *   Flow pattern to translate.
   11090                 :            :  * @param[in] inner
   11091                 :            :  *   Item is inner pattern.
   11092                 :            :  * @param[in] key_type
   11093                 :            :  *   Set flow matcher mask or value.
   11094                 :            :  */
   11095                 :            : static void
   11096                 :          0 : flow_dv_translate_item_icmp6(void *key, const struct rte_flow_item *item,
   11097                 :            :                              int inner, uint32_t key_type)
   11098                 :            : {
   11099                 :            :         const struct rte_flow_item_icmp6 *icmp6_m;
   11100                 :            :         const struct rte_flow_item_icmp6 *icmp6_v;
   11101                 :            :         void *headers_v;
   11102                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11103                 :            : 
   11104         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11105                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11106         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11107         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xFF);
   11108                 :            :         else
   11109         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
   11110                 :            :                          IPPROTO_ICMPV6);
   11111   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11112                 :            :                 return;
   11113   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp6_v, icmp6_m,
             #  #  #  # ]
   11114                 :            :                 &rte_flow_item_icmp6_mask);
   11115         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type,
   11116                 :            :                  icmp6_v->type & icmp6_m->type);
   11117         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code,
   11118                 :            :                  icmp6_v->code & icmp6_m->code);
   11119                 :            : }
   11120                 :            : 
   11121                 :            : /**
   11122                 :            :  * Add ICMP6 echo request/reply item to the value.
   11123                 :            :  *
   11124                 :            :  * @param[in, out] key
   11125                 :            :  *   Flow matcher value.
   11126                 :            :  * @param[in] item
   11127                 :            :  *   Flow pattern to translate.
   11128                 :            :  * @param[in] inner
   11129                 :            :  *   Item is inner pattern.
   11130                 :            :  * @param[in] key_type
   11131                 :            :  *   Set flow matcher mask or value.
   11132                 :            :  */
   11133                 :            : static void
   11134         [ #  # ]:          0 : flow_dv_translate_item_icmp6_echo(void *key, const struct rte_flow_item *item,
   11135                 :            :                                   int inner, uint32_t key_type)
   11136                 :            : {
   11137                 :            :         const struct rte_flow_item_icmp6_echo *icmp6_m;
   11138                 :            :         const struct rte_flow_item_icmp6_echo *icmp6_v;
   11139                 :            :         uint32_t icmp6_header_data_m = 0;
   11140                 :            :         uint32_t icmp6_header_data_v = 0;
   11141                 :            :         void *headers_v;
   11142                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11143                 :            :         uint8_t icmp6_type = 0;
   11144                 :            :         struct rte_flow_item_icmp6_echo zero_mask;
   11145                 :            : 
   11146                 :            :         memset(&zero_mask, 0, sizeof(zero_mask));
   11147         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11148                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11149         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11150         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xFF);
   11151                 :            :         else
   11152         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
   11153                 :            :                          IPPROTO_ICMPV6);
   11154   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp6_v, icmp6_m, &zero_mask);
             #  #  #  # ]
   11155                 :            :         /* Set fixed type and code for icmpv6 echo request or reply */
   11156         [ #  # ]:          0 :         icmp6_type = (item->type == RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST ?
   11157                 :            :                       RTE_ICMP6_ECHO_REQUEST : RTE_ICMP6_ECHO_REPLY);
   11158         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   11159         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, 0xFF);
   11160         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 0xFF);
   11161                 :            :         } else {
   11162         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, icmp6_type);
   11163         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 0);
   11164                 :            :         }
   11165         [ #  # ]:          0 :         if (icmp6_v == NULL)
   11166                 :          0 :                 return;
   11167                 :            :         /* Set icmp6 header data (identifier & sequence) accordingly */
   11168                 :          0 :         icmp6_header_data_m =
   11169         [ #  # ]:          0 :                 (rte_be_to_cpu_16(icmp6_m->hdr.identifier) << 16) |
   11170         [ #  # ]:          0 :                 rte_be_to_cpu_16(icmp6_m->hdr.sequence);
   11171         [ #  # ]:          0 :         if (icmp6_header_data_m) {
   11172                 :          0 :                 icmp6_header_data_v =
   11173         [ #  # ]:          0 :                         (rte_be_to_cpu_16(icmp6_v->hdr.identifier) << 16) |
   11174         [ #  # ]:          0 :                         rte_be_to_cpu_16(icmp6_v->hdr.sequence);
   11175         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_header_data,
   11176                 :            :                          icmp6_header_data_v & icmp6_header_data_m);
   11177                 :            :         }
   11178                 :            : }
   11179                 :            : 
   11180                 :            : /**
   11181                 :            :  * Add ICMP item to the value.
   11182                 :            :  *
   11183                 :            :  * @param[in, out] key
   11184                 :            :  *   Flow matcher value.
   11185                 :            :  * @param[in] item
   11186                 :            :  *   Flow pattern to translate.
   11187                 :            :  * @param[in] inner
   11188                 :            :  *   Item is inner pattern.
   11189                 :            :  * @param[in] key_type
   11190                 :            :  *   Set flow matcher mask or value.
   11191                 :            :  */
   11192                 :            : static void
   11193                 :          0 : flow_dv_translate_item_icmp(void *key, const struct rte_flow_item *item,
   11194                 :            :                             int inner, uint32_t key_type)
   11195                 :            : {
   11196                 :            :         const struct rte_flow_item_icmp *icmp_m;
   11197                 :            :         const struct rte_flow_item_icmp *icmp_v;
   11198                 :            :         uint32_t icmp_header_data_m = 0;
   11199                 :            :         uint32_t icmp_header_data_v = 0;
   11200                 :            :         void *headers_v;
   11201                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11202                 :            : 
   11203         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11204                 :            :                         MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11205         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11206         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11207                 :            :                          ip_protocol, 0xFF);
   11208                 :            :         else
   11209         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11210                 :            :                          ip_protocol, IPPROTO_ICMP);
   11211   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11212                 :            :                 return;
   11213   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp_v, icmp_m,
             #  #  #  # ]
   11214                 :            :                 &rte_flow_item_icmp_mask);
   11215         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmp_type,
   11216                 :            :                  icmp_v->hdr.icmp_type & icmp_m->hdr.icmp_type);
   11217         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmp_code,
   11218                 :            :                  icmp_v->hdr.icmp_code & icmp_m->hdr.icmp_code);
   11219         [ #  # ]:          0 :         icmp_header_data_m = rte_be_to_cpu_16(icmp_m->hdr.icmp_seq_nb);
   11220         [ #  # ]:          0 :         icmp_header_data_m |= rte_be_to_cpu_16(icmp_m->hdr.icmp_ident) << 16;
   11221         [ #  # ]:          0 :         if (icmp_header_data_m) {
   11222         [ #  # ]:          0 :                 icmp_header_data_v = rte_be_to_cpu_16(icmp_v->hdr.icmp_seq_nb);
   11223                 :          0 :                 icmp_header_data_v |=
   11224         [ #  # ]:          0 :                          rte_be_to_cpu_16(icmp_v->hdr.icmp_ident) << 16;
   11225         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmp_header_data,
   11226                 :            :                          icmp_header_data_v & icmp_header_data_m);
   11227                 :            :         }
   11228                 :            : }
   11229                 :            : 
   11230                 :            : /**
   11231                 :            :  * Add GTP item to the value.
   11232                 :            :  *
   11233                 :            :  * @param[in, out] key
   11234                 :            :  *   Flow matcher value.
   11235                 :            :  * @param[in] item
   11236                 :            :  *   Flow pattern to translate.
   11237                 :            :  * @param[in] inner
   11238                 :            :  *   Item is inner pattern.
   11239                 :            :  * @param[in] key_type
   11240                 :            :  *   Set flow matcher mask or value.
   11241                 :            :  */
   11242                 :            : static void
   11243                 :          0 : flow_dv_translate_item_gtp(void *key, const struct rte_flow_item *item,
   11244                 :            :                            int inner, uint32_t key_type)
   11245                 :            : {
   11246                 :            :         const struct rte_flow_item_gtp *gtp_m;
   11247                 :            :         const struct rte_flow_item_gtp *gtp_v;
   11248                 :            :         void *headers_v;
   11249                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11250                 :            :         uint16_t dport = RTE_GTPU_UDP_PORT;
   11251                 :            : 
   11252         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11253                 :            :                         MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11254   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   11255         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   11256         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11257                 :            :                                  udp_dport, 0xFFFF);
   11258                 :            :                 else
   11259         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11260                 :            :                                  udp_dport, dport);
   11261                 :            :         }
   11262   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11263                 :            :                 return;
   11264   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, gtp_v, gtp_m,
             #  #  #  # ]
   11265                 :            :                 &rte_flow_item_gtp_mask);
   11266         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags,
   11267                 :            :                  gtp_v->hdr.gtp_hdr_info & gtp_m->hdr.gtp_hdr_info);
   11268         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_type,
   11269                 :            :                  gtp_v->hdr.msg_type & gtp_m->hdr.msg_type);
   11270   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_teid,
   11271                 :            :                  rte_be_to_cpu_32(gtp_v->hdr.teid & gtp_m->hdr.teid));
   11272                 :            : }
   11273                 :            : 
   11274                 :            : /**
   11275                 :            :  * Add GTP PSC item to matcher.
   11276                 :            :  *
   11277                 :            :  * @param[in, out] key
   11278                 :            :  *   Flow matcher value.
   11279                 :            :  * @param[in] item
   11280                 :            :  *   Flow pattern to translate.
   11281                 :            :  * @param[in] key_type
   11282                 :            :  *   Set flow matcher mask or value.
   11283                 :            :  */
   11284                 :            : static int
   11285                 :          0 : flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
   11286                 :            :                                uint32_t key_type)
   11287                 :            : {
   11288                 :            :         const struct rte_flow_item_gtp_psc *gtp_psc_m;
   11289                 :            :         const struct rte_flow_item_gtp_psc *gtp_psc_v;
   11290                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11291                 :            :         union {
   11292                 :            :                 uint32_t w32;
   11293                 :            :                 struct {
   11294                 :            :                         uint16_t seq_num;
   11295                 :            :                         uint8_t npdu_num;
   11296                 :            :                         uint8_t next_ext_header_type;
   11297                 :            :                 };
   11298                 :            :         } dw_2;
   11299                 :            :         union {
   11300                 :            :                 uint32_t w32;
   11301                 :            :                 struct {
   11302                 :            :                         uint8_t len;
   11303                 :            :                         uint8_t type_flags;
   11304                 :            :                         uint8_t qfi;
   11305                 :            :                         uint8_t reserved;
   11306                 :            :                 };
   11307                 :            :         } dw_0;
   11308                 :            :         uint8_t gtp_flags;
   11309                 :            : 
   11310                 :            :         /* Always set E-flag match on one, regardless of GTP item settings. */
   11311         [ #  # ]:          0 :         gtp_flags = MLX5_GET(fte_match_set_misc3, misc3_v, gtpu_msg_flags);
   11312                 :          0 :         gtp_flags |= MLX5_GTP_EXT_HEADER_FLAG;
   11313         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags, gtp_flags);
   11314                 :            :         /*Set next extension header type. */
   11315                 :          0 :         dw_2.seq_num = 0;
   11316                 :          0 :         dw_2.npdu_num = 0;
   11317         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11318                 :          0 :                 dw_2.next_ext_header_type = 0xff;
   11319                 :            :         else
   11320                 :          0 :                 dw_2.next_ext_header_type = 0x85;
   11321   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_dw_2,
   11322                 :            :                  rte_cpu_to_be_32(dw_2.w32));
   11323   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11324                 :            :                 return 0;
   11325   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, gtp_psc_v,
             #  #  #  # ]
   11326                 :            :                 gtp_psc_m, &rte_flow_item_gtp_psc_mask);
   11327                 :          0 :         dw_0.w32 = 0;
   11328                 :          0 :         dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->hdr.type &
   11329                 :            :                                                   gtp_psc_m->hdr.type);
   11330                 :          0 :         dw_0.qfi = gtp_psc_v->hdr.qfi & gtp_psc_m->hdr.qfi;
   11331   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_first_ext_dw_0,
   11332                 :            :                  rte_cpu_to_be_32(dw_0.w32));
   11333                 :          0 :         return 0;
   11334                 :            : }
   11335                 :            : 
   11336                 :            : /**
   11337                 :            :  * Add eCPRI item to matcher and to the value.
   11338                 :            :  *
   11339                 :            :  * @param[in] dev
   11340                 :            :  *   The devich to configure through.
   11341                 :            :  * @param[in, out] key
   11342                 :            :  *   Flow matcher value.
   11343                 :            :  * @param[in] item
   11344                 :            :  *   Flow pattern to translate.
   11345                 :            :  * @param[in] last_item
   11346                 :            :  *   Last item flags.
   11347                 :            :  * @param[in] key_type
   11348                 :            :  *   Set flow matcher mask or value.
   11349                 :            :  */
   11350                 :            : static void
   11351                 :          0 : flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
   11352                 :            :                              const struct rte_flow_item *item,
   11353                 :            :                              uint64_t last_item, uint32_t key_type)
   11354                 :            : {
   11355                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11356                 :            :         const struct rte_flow_item_ecpri *ecpri_m;
   11357                 :            :         const struct rte_flow_item_ecpri *ecpri_v;
   11358                 :          0 :         const struct rte_flow_item_ecpri *ecpri_vv = item->spec;
   11359                 :            :         struct rte_ecpri_common_hdr common;
   11360                 :            :         void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4);
   11361                 :            :         uint32_t *samples;
   11362                 :            :         void *dw_v;
   11363                 :            : 
   11364                 :            :         /*
   11365                 :            :          * In case of eCPRI over Ethernet, if EtherType is not specified,
   11366                 :            :          * match on eCPRI EtherType implicitly.
   11367                 :            :          */
   11368         [ #  # ]:          0 :         if (last_item & MLX5_FLOW_LAYER_OUTER_L2) {
   11369                 :            :                 void *hdrs_v, *l2v;
   11370                 :            : 
   11371                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11372                 :            :                 l2v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
   11373         [ #  # ]:          0 :                 if (*(uint16_t *)l2v == 0) {
   11374         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   11375                 :          0 :                                 *(uint16_t *)l2v = UINT16_MAX;
   11376                 :            :                         else
   11377                 :          0 :                                 *(uint16_t *)l2v =
   11378                 :            :                                         RTE_BE16(RTE_ETHER_TYPE_ECPRI);
   11379                 :            :                 }
   11380                 :            :         }
   11381   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11382                 :          0 :                 return;
   11383   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m,
             #  #  #  # ]
   11384                 :            :                 &rte_flow_item_ecpri_mask);
   11385                 :            :         /*
   11386                 :            :          * Maximal four DW samples are supported in a single matching now.
   11387                 :            :          * Two are used now for a eCPRI matching:
   11388                 :            :          * 1. Type: one byte, mask should be 0x00ff0000 in network order
   11389                 :            :          * 2. ID of a message: one or two bytes, mask 0xffff0000 or 0xff000000
   11390                 :            :          *    if any.
   11391                 :            :          */
   11392         [ #  # ]:          0 :         if (!ecpri_m->hdr.common.u32)
   11393                 :            :                 return;
   11394                 :          0 :         samples = priv->sh->ecpri_parser.ids;
   11395                 :            :         /* Need to take the whole DW as the mask to fill the entry. */
   11396                 :            :         dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
   11397                 :            :                             prog_sample_field_value_0);
   11398                 :            :         /* Already big endian (network order) in the header. */
   11399                 :          0 :         *(uint32_t *)dw_v = ecpri_v->hdr.common.u32 & ecpri_m->hdr.common.u32;
   11400                 :            :         /* Sample#0, used for matching type, offset 0. */
   11401                 :            :         /* It makes no sense to set the sample ID in the mask field. */
   11402         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc4, misc4_v,
   11403                 :            :                  prog_sample_field_id_0, samples[0]);
   11404                 :            :         /*
   11405                 :            :          * Checking if message body part needs to be matched.
   11406                 :            :          * Some wildcard rules only matching type field should be supported.
   11407                 :            :          */
   11408         [ #  # ]:          0 :         if (ecpri_m->hdr.dummy[0]) {
   11409         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M)
   11410         [ #  # ]:          0 :                         common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
   11411                 :            :                 else
   11412         [ #  # ]:          0 :                         common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
   11413         [ #  # ]:          0 :                 switch (common.type) {
   11414                 :          0 :                 case RTE_ECPRI_MSG_TYPE_IQ_DATA:
   11415                 :            :                 case RTE_ECPRI_MSG_TYPE_RTC_CTRL:
   11416                 :            :                 case RTE_ECPRI_MSG_TYPE_DLY_MSR:
   11417                 :            :                         dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
   11418                 :            :                                             prog_sample_field_value_1);
   11419                 :          0 :                         *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] &
   11420                 :            :                                             ecpri_m->hdr.dummy[0];
   11421                 :            :                         /* Sample#1, to match message body, offset 4. */
   11422         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_misc4, misc4_v,
   11423                 :            :                                  prog_sample_field_id_1, samples[1]);
   11424                 :          0 :                         break;
   11425                 :            :                 default:
   11426                 :            :                         /* Others, do not match any sample ID. */
   11427                 :            :                         break;
   11428                 :            :                 }
   11429                 :            :         }
   11430                 :            : }
   11431                 :            : 
   11432                 :            : /*
   11433                 :            :  * Add connection tracking status item to matcher
   11434                 :            :  *
   11435                 :            :  * @param[in] dev
   11436                 :            :  *   The devich to configure through.
   11437                 :            :  * @param[in, out] matcher
   11438                 :            :  *   Flow matcher.
   11439                 :            :  * @param[in, out] key
   11440                 :            :  *   Flow matcher value.
   11441                 :            :  * @param[in] item
   11442                 :            :  *   Flow pattern to translate.
   11443                 :            :  */
   11444                 :            : static void
   11445                 :          0 : flow_dv_translate_item_aso_ct(struct rte_eth_dev *dev,
   11446                 :            :                               void *matcher, void *key,
   11447                 :            :                               const struct rte_flow_item *item)
   11448                 :            : {
   11449                 :            :         uint32_t reg_value = 0;
   11450                 :            :         int reg_id;
   11451                 :            :         /* 8LSB 0b 11/0000/11, middle 4 bits are reserved. */
   11452                 :            :         uint32_t reg_mask = 0;
   11453                 :          0 :         const struct rte_flow_item_conntrack *spec = item->spec;
   11454                 :          0 :         const struct rte_flow_item_conntrack *mask = item->mask;
   11455                 :            :         uint32_t flags;
   11456                 :            :         struct rte_flow_error error;
   11457                 :            : 
   11458         [ #  # ]:          0 :         if (!mask)
   11459                 :            :                 mask = &rte_flow_item_conntrack_mask;
   11460   [ #  #  #  # ]:          0 :         if (!spec || !mask->flags)
   11461                 :          0 :                 return;
   11462                 :          0 :         flags = spec->flags & mask->flags;
   11463                 :            :         /* The conflict should be checked in the validation. */
   11464                 :            :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_VALID)
   11465                 :            :                 reg_value |= MLX5_CT_SYNDROME_VALID;
   11466         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
   11467                 :            :                 reg_value |= MLX5_CT_SYNDROME_STATE_CHANGE;
   11468         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_INVALID)
   11469                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_INVALID;
   11470         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED)
   11471                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_TRAP;
   11472         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
   11473                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_BAD_PACKET;
   11474         [ #  # ]:          0 :         if (mask->flags & (RTE_FLOW_CONNTRACK_PKT_STATE_VALID |
   11475                 :            :                            RTE_FLOW_CONNTRACK_PKT_STATE_INVALID |
   11476                 :            :                            RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED))
   11477                 :            :                 reg_mask |= 0xc0;
   11478         [ #  # ]:          0 :         if (mask->flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
   11479                 :          0 :                 reg_mask |= MLX5_CT_SYNDROME_STATE_CHANGE;
   11480         [ #  # ]:          0 :         if (mask->flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
   11481                 :          0 :                 reg_mask |= MLX5_CT_SYNDROME_BAD_PACKET;
   11482                 :            :         /* The REG_C_x value could be saved during startup. */
   11483                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, &error);
   11484         [ #  # ]:          0 :         if (reg_id == REG_NON)
   11485                 :            :                 return;
   11486                 :          0 :         flow_dv_match_meta_reg_all(matcher, key, (enum modify_reg)reg_id,
   11487                 :            :                                reg_value, reg_mask);
   11488                 :            : }
   11489                 :            : 
   11490                 :            : static void
   11491                 :          0 : flow_dv_translate_item_flex(struct rte_eth_dev *dev, void *matcher, void *key,
   11492                 :            :                             const struct rte_flow_item *item,
   11493                 :            :                             struct mlx5_flow *dev_flow, bool is_inner)
   11494                 :            : {
   11495                 :          0 :         const struct rte_flow_item_flex *spec =
   11496                 :            :                 (const struct rte_flow_item_flex *)item->spec;
   11497                 :          0 :         int index = mlx5_flex_acquire_index(dev, spec->handle, false);
   11498                 :            : 
   11499                 :            :         MLX5_ASSERT(index >= 0 && index < (int)(sizeof(uint32_t) * CHAR_BIT));
   11500         [ #  # ]:          0 :         if (index < 0)
   11501                 :            :                 return;
   11502         [ #  # ]:          0 :         if (!(dev_flow->handle->flex_item & RTE_BIT32(index))) {
   11503                 :            :                 /* Don't count both inner and outer flex items in one rule. */
   11504                 :          0 :                 if (mlx5_flex_acquire_index(dev, spec->handle, true) != index)
   11505                 :            :                         MLX5_ASSERT(false);
   11506                 :          0 :                 dev_flow->handle->flex_item |= (uint8_t)RTE_BIT32(index);
   11507                 :            :         }
   11508                 :          0 :         mlx5_flex_flow_translate_item(dev, matcher, key, item, is_inner);
   11509                 :            : }
   11510                 :            : 
   11511                 :            : /**
   11512                 :            :  * Add METER_COLOR item to matcher
   11513                 :            :  *
   11514                 :            :  * @param[in] dev
   11515                 :            :  *   The device to configure through.
   11516                 :            :  * @param[in, out] key
   11517                 :            :  *   Flow matcher value.
   11518                 :            :  * @param[in] item
   11519                 :            :  *   Flow pattern to translate.
   11520                 :            :  * @param[in] key_type
   11521                 :            :  *   Set flow matcher mask or value.
   11522                 :            :  */
   11523                 :            : static void
   11524                 :          0 : flow_dv_translate_item_meter_color(struct rte_eth_dev *dev, void *key,
   11525                 :            :                             const struct rte_flow_item *item,
   11526                 :            :                             uint32_t key_type)
   11527                 :            : {
   11528                 :          0 :         const struct rte_flow_item_meter_color *color_m = item->mask;
   11529                 :          0 :         const struct rte_flow_item_meter_color *color_v = item->spec;
   11530                 :            :         uint32_t value, mask;
   11531                 :            :         int reg = REG_NON;
   11532                 :            : 
   11533                 :            :         MLX5_ASSERT(color_v);
   11534   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11535                 :            :                 return;
   11536   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, color_v, color_m,
             #  #  #  # ]
   11537                 :            :                 &rte_flow_item_meter_color_mask);
   11538         [ #  # ]:          0 :         value = rte_col_2_mlx5_col(color_v->color);
   11539                 :            :         mask = color_m ?
   11540         [ #  # ]:          0 :                 color_m->color : (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
   11541         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   11542                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
   11543                 :            :         else
   11544                 :            :                 reg = flow_hw_get_reg_id(dev,
   11545                 :            :                                          RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
   11546         [ #  # ]:          0 :         if (reg == REG_NON)
   11547                 :            :                 return;
   11548                 :          0 :         flow_dv_match_meta_reg(key, (enum modify_reg)reg, value, mask);
   11549                 :            : }
   11550                 :            : 
   11551                 :            : static void
   11552                 :          0 : flow_dv_translate_item_aggr_affinity(void *key,
   11553                 :            :                                     const struct rte_flow_item *item,
   11554                 :            :                                     uint32_t key_type)
   11555                 :            : {
   11556                 :            :         const struct rte_flow_item_aggr_affinity *affinity_v;
   11557                 :            :         const struct rte_flow_item_aggr_affinity *affinity_m;
   11558                 :            :         void *misc_v;
   11559                 :            : 
   11560   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, affinity_v, affinity_m,
             #  #  #  # ]
   11561                 :            :                          &rte_flow_item_aggr_affinity_mask);
   11562                 :            :         misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   11563         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, lag_rx_port_affinity,
   11564                 :            :                  affinity_v->affinity & affinity_m->affinity);
   11565                 :          0 : }
   11566                 :            : 
   11567                 :            : static void
   11568                 :          0 : flow_dv_translate_item_ib_bth(void *key,
   11569                 :            :                               const struct rte_flow_item *item,
   11570                 :            :                               int inner, uint32_t key_type)
   11571                 :            : {
   11572                 :            :         const struct rte_flow_item_ib_bth *bth_m;
   11573                 :            :         const struct rte_flow_item_ib_bth *bth_v;
   11574                 :            :         void *headers_v, *misc_v;
   11575                 :            :         uint16_t udp_dport;
   11576                 :            :         char *qpn_v;
   11577                 :            :         int i, size;
   11578                 :            : 
   11579         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11580                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11581   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   11582         [ #  # ]:          0 :                 udp_dport = key_type & MLX5_SET_MATCHER_M ?
   11583                 :            :                         0xFFFF : MLX5_UDP_PORT_ROCEv2;
   11584         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, udp_dport);
   11585                 :            :         }
   11586   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11587                 :            :                 return;
   11588   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, bth_v, bth_m, &rte_flow_item_ib_bth_mask);
             #  #  #  # ]
   11589                 :            :         misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   11590         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, bth_opcode,
   11591                 :            :                  bth_v->hdr.opcode & bth_m->hdr.opcode);
   11592                 :          0 :         qpn_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, bth_dst_qp);
   11593                 :            :         size = sizeof(bth_m->hdr.dst_qp);
   11594         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   11595                 :          0 :                 qpn_v[i] = bth_m->hdr.dst_qp[i] & bth_v->hdr.dst_qp[i];
   11596                 :            : }
   11597                 :            : 
   11598                 :            : static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
   11599                 :            : 
   11600                 :            : #define HEADER_IS_ZERO(match_criteria, headers)                              \
   11601                 :            :         !(memcmp(MLX5_ADDR_OF(fte_match_param, match_criteria, headers),     \
   11602                 :            :                  matcher_zero, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \
   11603                 :            : 
   11604                 :            : /**
   11605                 :            :  * Calculate flow matcher enable bitmap.
   11606                 :            :  *
   11607                 :            :  * @param match_criteria
   11608                 :            :  *   Pointer to flow matcher criteria.
   11609                 :            :  *
   11610                 :            :  * @return
   11611                 :            :  *   Bitmap of enabled fields.
   11612                 :            :  */
   11613                 :            : static uint8_t
   11614                 :          0 : flow_dv_matcher_enable(uint32_t *match_criteria)
   11615                 :            : {
   11616                 :            :         uint8_t match_criteria_enable;
   11617                 :            : 
   11618                 :            :         match_criteria_enable =
   11619                 :          0 :                 (!HEADER_IS_ZERO(match_criteria, outer_headers)) <<
   11620                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_OUTER_BIT;
   11621                 :          0 :         match_criteria_enable |=
   11622         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters)) <<
   11623                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC_BIT;
   11624                 :          0 :         match_criteria_enable |=
   11625         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, inner_headers)) <<
   11626                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_INNER_BIT;
   11627                 :          0 :         match_criteria_enable |=
   11628         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) <<
   11629                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT;
   11630                 :          0 :         match_criteria_enable |=
   11631         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_3)) <<
   11632                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC3_BIT;
   11633                 :          0 :         match_criteria_enable |=
   11634         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_4)) <<
   11635                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT;
   11636                 :          0 :         match_criteria_enable |=
   11637         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_5)) <<
   11638                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC5_BIT;
   11639                 :          0 :         return match_criteria_enable;
   11640                 :            : }
   11641                 :            : 
   11642                 :            : static void
   11643                 :            : __flow_dv_adjust_buf_size(size_t *size, uint8_t match_criteria)
   11644                 :            : {
   11645                 :            :         /*
   11646                 :            :          * Check flow matching criteria first, subtract misc5/4 length if flow
   11647                 :            :          * doesn't own misc5/4 parameters. In some old rdma-core releases,
   11648                 :            :          * misc5/4 are not supported, and matcher creation failure is expected
   11649                 :            :          * w/o subtraction. If misc5 is provided, misc4 must be counted in since
   11650                 :            :          * misc5 is right after misc4.
   11651                 :            :          */
   11652                 :          0 :         if (!(match_criteria & (1 << MLX5_MATCH_CRITERIA_ENABLE_MISC5_BIT))) {
   11653                 :          0 :                 *size = MLX5_ST_SZ_BYTES(fte_match_param) -
   11654                 :            :                         MLX5_ST_SZ_BYTES(fte_match_set_misc5);
   11655   [ #  #  #  #  :          0 :                 if (!(match_criteria & (1 <<
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
   11656                 :            :                         MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT))) {
   11657                 :          0 :                         *size -= MLX5_ST_SZ_BYTES(fte_match_set_misc4);
   11658                 :            :                 }
   11659                 :            :         }
   11660                 :            : }
   11661                 :            : 
   11662                 :            : struct mlx5_list_entry *
   11663                 :          0 : flow_matcher_clone_cb(void *tool_ctx __rte_unused,
   11664                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
   11665                 :            : {
   11666                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11667                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11668                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(ref->tbl,
   11669                 :            :                                                             typeof(*tbl), tbl);
   11670                 :          0 :         struct mlx5_flow_dv_matcher *resource = mlx5_malloc(MLX5_MEM_ANY,
   11671                 :            :                                                             sizeof(*resource),
   11672                 :            :                                                             0, SOCKET_ID_ANY);
   11673                 :            : 
   11674         [ #  # ]:          0 :         if (!resource) {
   11675                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11676                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11677                 :            :                                    "cannot create matcher");
   11678                 :          0 :                 return NULL;
   11679                 :            :         }
   11680                 :            :         memcpy(resource, entry, sizeof(*resource));
   11681                 :          0 :         resource->tbl = &tbl->tbl;
   11682                 :          0 :         return &resource->entry;
   11683                 :            : }
   11684                 :            : 
   11685                 :            : void
   11686                 :          0 : flow_matcher_clone_free_cb(void *tool_ctx __rte_unused,
   11687                 :            :                              struct mlx5_list_entry *entry)
   11688                 :            : {
   11689                 :          0 :         mlx5_free(entry);
   11690                 :          0 : }
   11691                 :            : 
   11692                 :            : struct mlx5_list_entry *
   11693                 :          0 : flow_dv_tbl_create_cb(void *tool_ctx, void *cb_ctx)
   11694                 :            : {
   11695                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11696                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11697                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   11698                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11699                 :          0 :         struct mlx5_flow_tbl_tunnel_prm *tt_prm = ctx->data2;
   11700                 :          0 :         struct rte_flow_error *error = ctx->error;
   11701                 :          0 :         union mlx5_flow_tbl_key key = { .v64 = *(uint64_t *)(ctx->data) };
   11702                 :            :         struct mlx5_flow_tbl_resource *tbl;
   11703                 :            :         void *domain;
   11704                 :          0 :         uint32_t idx = 0;
   11705                 :            :         int ret;
   11706                 :            : 
   11707                 :          0 :         tbl_data = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_JUMP], &idx);
   11708         [ #  # ]:          0 :         if (!tbl_data) {
   11709                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11710                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11711                 :            :                                    NULL,
   11712                 :            :                                    "cannot allocate flow table data entry");
   11713                 :          0 :                 return NULL;
   11714                 :            :         }
   11715                 :          0 :         tbl_data->idx = idx;
   11716                 :          0 :         tbl_data->tunnel = tt_prm->tunnel;
   11717                 :          0 :         tbl_data->group_id = tt_prm->group_id;
   11718         [ #  # ]:          0 :         tbl_data->external = !!tt_prm->external;
   11719                 :          0 :         tbl_data->tunnel_offload = is_tunnel_offload_active(dev);
   11720                 :          0 :         tbl_data->is_egress = !!key.is_egress;
   11721                 :          0 :         tbl_data->is_transfer = !!key.is_fdb;
   11722                 :          0 :         tbl_data->dummy = !!key.dummy;
   11723                 :          0 :         tbl_data->level = key.level;
   11724                 :          0 :         tbl_data->id = key.id;
   11725                 :            :         tbl = &tbl_data->tbl;
   11726         [ #  # ]:          0 :         if (key.dummy)
   11727                 :          0 :                 return &tbl_data->entry;
   11728         [ #  # ]:          0 :         if (key.is_fdb)
   11729                 :          0 :                 domain = sh->fdb_domain;
   11730         [ #  # ]:          0 :         else if (key.is_egress)
   11731                 :          0 :                 domain = sh->tx_domain;
   11732                 :            :         else
   11733                 :          0 :                 domain = sh->rx_domain;
   11734                 :            :         ret = mlx5_flow_os_create_flow_tbl(domain, key.level, &tbl->obj);
   11735                 :            :         if (ret) {
   11736                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11737                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11738                 :            :                                    NULL, "cannot create flow table object");
   11739                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11740                 :          0 :                 return NULL;
   11741                 :            :         }
   11742         [ #  # ]:          0 :         if (key.level != 0) {
   11743                 :            :                 ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
   11744                 :            :                                         (tbl->obj, &tbl_data->jump.action);
   11745                 :            :                 if (ret) {
   11746                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   11747                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11748                 :            :                                            NULL,
   11749                 :            :                                            "cannot create flow jump action");
   11750                 :          0 :                         mlx5_flow_os_destroy_flow_tbl(tbl->obj);
   11751                 :          0 :                         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11752                 :          0 :                         return NULL;
   11753                 :            :                 }
   11754                 :            :         }
   11755   [ #  #  #  # ]:          0 :         MKSTR(matcher_name, "%s_%s_%u_%u_matcher_list",
   11756                 :            :               key.is_fdb ? "FDB" : "NIC", key.is_egress ? "egress" : "ingress",
   11757                 :            :               key.level, key.id);
   11758                 :          0 :         tbl_data->matchers = mlx5_list_create(matcher_name, sh, true,
   11759                 :            :                                               flow_matcher_create_cb,
   11760                 :            :                                               flow_matcher_match_cb,
   11761                 :            :                                               flow_matcher_remove_cb,
   11762                 :            :                                               flow_matcher_clone_cb,
   11763                 :            :                                               flow_matcher_clone_free_cb);
   11764         [ #  # ]:          0 :         if (!tbl_data->matchers) {
   11765                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11766                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11767                 :            :                                    NULL,
   11768                 :            :                                    "cannot create tbl matcher list");
   11769                 :          0 :                 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action);
   11770                 :          0 :                 mlx5_flow_os_destroy_flow_tbl(tbl->obj);
   11771                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11772                 :          0 :                 return NULL;
   11773                 :            :         }
   11774                 :          0 :         return &tbl_data->entry;
   11775                 :            : }
   11776                 :            : 
   11777                 :            : int
   11778                 :          0 : flow_dv_tbl_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
   11779                 :            :                      void *cb_ctx)
   11780                 :            : {
   11781                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11782                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11783                 :            :                 container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11784                 :          0 :         union mlx5_flow_tbl_key key = { .v64 =  *(uint64_t *)(ctx->data) };
   11785                 :            : 
   11786                 :          0 :         return tbl_data->level != key.level ||
   11787         [ #  # ]:          0 :                tbl_data->id != key.id ||
   11788         [ #  # ]:          0 :                tbl_data->dummy != key.dummy ||
   11789   [ #  #  #  # ]:          0 :                tbl_data->is_transfer != !!key.is_fdb ||
   11790         [ #  # ]:          0 :                tbl_data->is_egress != !!key.is_egress;
   11791                 :            : }
   11792                 :            : 
   11793                 :            : struct mlx5_list_entry *
   11794                 :          0 : flow_dv_tbl_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
   11795                 :            :                       void *cb_ctx)
   11796                 :            : {
   11797                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11798                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11799                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11800                 :          0 :         struct rte_flow_error *error = ctx->error;
   11801                 :          0 :         uint32_t idx = 0;
   11802                 :            : 
   11803                 :          0 :         tbl_data = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_JUMP], &idx);
   11804         [ #  # ]:          0 :         if (!tbl_data) {
   11805                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11806                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11807                 :            :                                    NULL,
   11808                 :            :                                    "cannot allocate flow table data entry");
   11809                 :          0 :                 return NULL;
   11810                 :            :         }
   11811                 :            :         memcpy(tbl_data, oentry, sizeof(*tbl_data));
   11812                 :          0 :         tbl_data->idx = idx;
   11813                 :          0 :         return &tbl_data->entry;
   11814                 :            : }
   11815                 :            : 
   11816                 :            : void
   11817                 :          0 : flow_dv_tbl_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11818                 :            : {
   11819                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11820                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11821                 :            :                     container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11822                 :            : 
   11823                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx);
   11824                 :          0 : }
   11825                 :            : 
   11826                 :            : /**
   11827                 :            :  * Get a flow table.
   11828                 :            :  *
   11829                 :            :  * @param[in, out] dev
   11830                 :            :  *   Pointer to rte_eth_dev structure.
   11831                 :            :  * @param[in] table_level
   11832                 :            :  *   Table level to use.
   11833                 :            :  * @param[in] egress
   11834                 :            :  *   Direction of the table.
   11835                 :            :  * @param[in] transfer
   11836                 :            :  *   E-Switch or NIC flow.
   11837                 :            :  * @param[in] dummy
   11838                 :            :  *   Dummy entry for dv API.
   11839                 :            :  * @param[in] table_id
   11840                 :            :  *   Table id to use.
   11841                 :            :  * @param[out] error
   11842                 :            :  *   pointer to error structure.
   11843                 :            :  *
   11844                 :            :  * @return
   11845                 :            :  *   Returns tables resource based on the index, NULL in case of failed.
   11846                 :            :  */
   11847                 :            : struct mlx5_flow_tbl_resource *
   11848                 :          0 : flow_dv_tbl_resource_get(struct rte_eth_dev *dev,
   11849                 :            :                          uint32_t table_level, uint8_t egress,
   11850                 :            :                          uint8_t transfer,
   11851                 :            :                          bool external,
   11852                 :            :                          const struct mlx5_flow_tunnel *tunnel,
   11853                 :            :                          uint32_t group_id, uint8_t dummy,
   11854                 :            :                          uint32_t table_id,
   11855                 :            :                          struct rte_flow_error *error)
   11856                 :            : {
   11857                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11858                 :          0 :         union mlx5_flow_tbl_key table_key = {
   11859                 :            :                 {
   11860                 :            :                         .level = table_level,
   11861                 :            :                         .id = table_id,
   11862                 :            :                         .reserved = 0,
   11863                 :          0 :                         .dummy = !!dummy,
   11864                 :          0 :                         .is_fdb = !!transfer,
   11865                 :          0 :                         .is_egress = !!egress,
   11866                 :            :                 }
   11867                 :            :         };
   11868                 :          0 :         struct mlx5_flow_tbl_tunnel_prm tt_prm = {
   11869                 :            :                 .tunnel = tunnel,
   11870                 :            :                 .group_id = group_id,
   11871                 :            :                 .external = external,
   11872                 :            :         };
   11873                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   11874                 :            :                 .dev = dev,
   11875                 :            :                 .error = error,
   11876                 :            :                 .data = &table_key.v64,
   11877                 :            :                 .data2 = &tt_prm,
   11878                 :            :         };
   11879                 :            :         struct mlx5_list_entry *entry;
   11880                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11881                 :            : 
   11882                 :          0 :         entry = mlx5_hlist_register(priv->sh->flow_tbls, table_key.v64, &ctx);
   11883         [ #  # ]:          0 :         if (!entry) {
   11884                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11885                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11886                 :            :                                    "cannot get table");
   11887                 :          0 :                 return NULL;
   11888                 :            :         }
   11889         [ #  # ]:          0 :         DRV_LOG(DEBUG, "table_level %u table_id %u "
   11890                 :            :                 "tunnel %u group %u registered.",
   11891                 :            :                 table_level, table_id,
   11892                 :            :                 tunnel ? tunnel->tunnel_id : 0, group_id);
   11893                 :            :         tbl_data = container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11894                 :          0 :         return &tbl_data->tbl;
   11895                 :            : }
   11896                 :            : 
   11897                 :            : void
   11898                 :          0 : flow_dv_tbl_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11899                 :            : {
   11900                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11901                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11902                 :            :                     container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11903                 :            : 
   11904                 :            :         MLX5_ASSERT(entry && sh);
   11905         [ #  # ]:          0 :         if (tbl_data->jump.action)
   11906                 :            :                 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action);
   11907         [ #  # ]:          0 :         if (tbl_data->tbl.obj)
   11908                 :            :                 mlx5_flow_os_destroy_flow_tbl(tbl_data->tbl.obj);
   11909         [ #  # ]:          0 :         if (tbl_data->tunnel_offload && tbl_data->external) {
   11910                 :            :                 struct mlx5_list_entry *he;
   11911                 :            :                 struct mlx5_hlist *tunnel_grp_hash;
   11912                 :          0 :                 struct mlx5_flow_tunnel_hub *thub = sh->tunnel_hub;
   11913                 :          0 :                 union tunnel_tbl_key tunnel_key = {
   11914                 :          0 :                         .tunnel_id = tbl_data->tunnel ?
   11915         [ #  # ]:          0 :                                         tbl_data->tunnel->tunnel_id : 0,
   11916                 :          0 :                         .group = tbl_data->group_id
   11917                 :            :                 };
   11918                 :          0 :                 uint32_t table_level = tbl_data->level;
   11919                 :          0 :                 struct mlx5_flow_cb_ctx ctx = {
   11920                 :            :                         .data = (void *)&tunnel_key.val,
   11921                 :            :                 };
   11922                 :            : 
   11923                 :            :                 tunnel_grp_hash = tbl_data->tunnel ?
   11924         [ #  # ]:          0 :                                         tbl_data->tunnel->groups :
   11925                 :            :                                         thub->groups;
   11926                 :          0 :                 he = mlx5_hlist_lookup(tunnel_grp_hash, tunnel_key.val, &ctx);
   11927         [ #  # ]:          0 :                 if (he)
   11928                 :          0 :                         mlx5_hlist_unregister(tunnel_grp_hash, he);
   11929         [ #  # ]:          0 :                 DRV_LOG(DEBUG,
   11930                 :            :                         "table_level %u id %u tunnel %u group %u released.",
   11931                 :            :                         table_level,
   11932                 :            :                         tbl_data->id,
   11933                 :            :                         tbl_data->tunnel ?
   11934                 :            :                         tbl_data->tunnel->tunnel_id : 0,
   11935                 :            :                         tbl_data->group_id);
   11936                 :            :         }
   11937         [ #  # ]:          0 :         if (tbl_data->matchers)
   11938                 :          0 :                 mlx5_list_destroy(tbl_data->matchers);
   11939                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx);
   11940                 :          0 : }
   11941                 :            : 
   11942                 :            : /**
   11943                 :            :  * Release a flow table.
   11944                 :            :  *
   11945                 :            :  * @param[in] sh
   11946                 :            :  *   Pointer to device shared structure.
   11947                 :            :  * @param[in] tbl
   11948                 :            :  *   Table resource to be released.
   11949                 :            :  *
   11950                 :            :  * @return
   11951                 :            :  *   Returns 0 if table was released, else return 1;
   11952                 :            :  */
   11953                 :            : int
   11954                 :          0 : flow_dv_tbl_resource_release(struct mlx5_dev_ctx_shared *sh,
   11955                 :            :                              struct mlx5_flow_tbl_resource *tbl)
   11956                 :            : {
   11957                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11958                 :          0 :                 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
   11959                 :            : 
   11960         [ #  # ]:          0 :         if (!tbl)
   11961                 :            :                 return 0;
   11962                 :          0 :         return mlx5_hlist_unregister(sh->flow_tbls, &tbl_data->entry);
   11963                 :            : }
   11964                 :            : 
   11965                 :            : int
   11966                 :          0 : flow_matcher_match_cb(void *tool_ctx __rte_unused,
   11967                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
   11968                 :            : {
   11969                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11970                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11971                 :            :         struct mlx5_flow_dv_matcher *cur = container_of(entry, typeof(*cur),
   11972                 :            :                                                         entry);
   11973                 :            : 
   11974                 :          0 :         return cur->crc != ref->crc ||
   11975         [ #  # ]:          0 :                cur->priority != ref->priority ||
   11976                 :          0 :                memcmp((const void *)cur->mask.buf,
   11977         [ #  # ]:          0 :                       (const void *)ref->mask.buf, ref->mask.size);
   11978                 :            : }
   11979                 :            : 
   11980                 :            : struct mlx5_list_entry *
   11981                 :          0 : flow_matcher_create_cb(void *tool_ctx, void *cb_ctx)
   11982                 :            : {
   11983                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11984                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11985                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11986                 :            :         struct mlx5_flow_dv_matcher *resource;
   11987                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   11988                 :            :         const struct rte_flow_item *items;
   11989                 :            : #endif
   11990                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   11991                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   11992                 :          0 :                 .match_mask = (void *)&ref->mask,
   11993                 :            :         };
   11994                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   11995                 :            :         int ret;
   11996                 :            : 
   11997                 :          0 :         resource = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*resource), 0,
   11998                 :            :                                SOCKET_ID_ANY);
   11999         [ #  # ]:          0 :         if (!resource) {
   12000                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12001                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12002                 :            :                                    "cannot create matcher");
   12003                 :          0 :                 return NULL;
   12004                 :            :         }
   12005                 :          0 :         *resource = *ref;
   12006         [ #  # ]:          0 :         if (sh->config.dv_flow_en != 2) {
   12007                 :          0 :                 tbl = container_of(ref->tbl, typeof(*tbl), tbl);
   12008                 :          0 :                 dv_attr.match_criteria_enable =
   12009         [ #  # ]:          0 :                         flow_dv_matcher_enable(resource->mask.buf);
   12010                 :            :                 __flow_dv_adjust_buf_size(&ref->mask.size,
   12011                 :            :                                         dv_attr.match_criteria_enable);
   12012                 :          0 :                 dv_attr.priority = ref->priority;
   12013         [ #  # ]:          0 :                 if (tbl->is_egress)
   12014                 :          0 :                         dv_attr.flags |= IBV_FLOW_ATTR_FLAGS_EGRESS;
   12015                 :          0 :                 ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   12016                 :            :                                                 tbl->tbl.obj,
   12017                 :            :                                                 &resource->matcher_object);
   12018                 :            :                 if (ret) {
   12019                 :          0 :                         mlx5_free(resource);
   12020                 :          0 :                         rte_flow_error_set(ctx->error, ENOMEM,
   12021                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12022                 :            :                                         "cannot create matcher");
   12023                 :          0 :                         return NULL;
   12024                 :            :                 }
   12025                 :            :         } else {
   12026                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   12027                 :          0 :                 items = *((const struct rte_flow_item **)(ctx->data2));
   12028                 :          0 :                 resource->matcher_object = mlx5dr_bwc_matcher_create
   12029                 :          0 :                                 (resource->group->tbl, resource->priority, items);
   12030         [ #  # ]:          0 :                 if (!resource->matcher_object) {
   12031                 :          0 :                         mlx5_free(resource);
   12032                 :          0 :                         return NULL;
   12033                 :            :                 }
   12034                 :            : #else
   12035                 :            :                 mlx5_free(resource);
   12036                 :            :                 return NULL;
   12037                 :            : #endif
   12038                 :            :         }
   12039                 :          0 :         return &resource->entry;
   12040                 :            : }
   12041                 :            : 
   12042                 :            : /**
   12043                 :            :  * Register the flow matcher.
   12044                 :            :  *
   12045                 :            :  * @param[in, out] dev
   12046                 :            :  *   Pointer to rte_eth_dev structure.
   12047                 :            :  * @param[in, out] matcher
   12048                 :            :  *   Pointer to flow matcher.
   12049                 :            :  * @param[in, out] key
   12050                 :            :  *   Pointer to flow table key.
   12051                 :            :  * @parm[in, out] dev_flow
   12052                 :            :  *   Pointer to the dev_flow.
   12053                 :            :  * @param[out] error
   12054                 :            :  *   pointer to error structure.
   12055                 :            :  *
   12056                 :            :  * @return
   12057                 :            :  *   0 on success otherwise -errno and errno is set.
   12058                 :            :  */
   12059                 :            : static int
   12060                 :          0 : flow_dv_matcher_register(struct rte_eth_dev *dev,
   12061                 :            :                          struct mlx5_flow_dv_matcher *ref,
   12062                 :            :                          union mlx5_flow_tbl_key *key,
   12063                 :            :                          struct mlx5_flow *dev_flow,
   12064                 :            :                          const struct mlx5_flow_tunnel *tunnel,
   12065                 :            :                          uint32_t group_id,
   12066                 :            :                          struct rte_flow_error *error)
   12067                 :            : {
   12068                 :            :         struct mlx5_list_entry *entry;
   12069                 :            :         struct mlx5_flow_dv_matcher *resource;
   12070                 :            :         struct mlx5_flow_tbl_resource *tbl;
   12071                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   12072                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12073                 :            :                 .error = error,
   12074                 :            :                 .data = ref,
   12075                 :            :         };
   12076                 :            :         /**
   12077                 :            :          * tunnel offload API requires this registration for cases when
   12078                 :            :          * tunnel match rule was inserted before tunnel set rule.
   12079                 :            :          */
   12080                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, key->level,
   12081                 :          0 :                                        key->is_egress, key->is_fdb,
   12082                 :          0 :                                        dev_flow->external, tunnel,
   12083                 :          0 :                                        group_id, 0, key->id, error);
   12084         [ #  # ]:          0 :         if (!tbl)
   12085                 :          0 :                 return -rte_errno;      /* No need to refill the error info */
   12086                 :          0 :         tbl_data = container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
   12087                 :          0 :         ref->tbl = tbl;
   12088                 :          0 :         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   12089         [ #  # ]:          0 :         if (!entry) {
   12090                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   12091                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   12092                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12093                 :            :                                           "cannot allocate ref memory");
   12094                 :            :         }
   12095                 :            :         resource = container_of(entry, typeof(*resource), entry);
   12096                 :          0 :         dev_flow->handle->dvh.matcher = resource;
   12097                 :          0 :         return 0;
   12098                 :            : }
   12099                 :            : 
   12100                 :            : struct mlx5_list_entry *
   12101                 :          0 : flow_dv_tag_create_cb(void *tool_ctx, void *cb_ctx)
   12102                 :            : {
   12103                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12104                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12105                 :            :         struct mlx5_flow_dv_tag_resource *entry;
   12106                 :          0 :         uint32_t idx = 0;
   12107                 :            :         int ret;
   12108                 :            : 
   12109                 :          0 :         entry = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_TAG], &idx);
   12110         [ #  # ]:          0 :         if (!entry) {
   12111                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12112                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12113                 :            :                                    "cannot allocate resource memory");
   12114                 :          0 :                 return NULL;
   12115                 :            :         }
   12116                 :          0 :         entry->idx = idx;
   12117                 :          0 :         entry->tag_id = *(uint32_t *)(ctx->data);
   12118                 :            :         ret = mlx5_flow_os_create_flow_action_tag(entry->tag_id,
   12119                 :            :                                                   &entry->action);
   12120                 :            :         if (ret) {
   12121                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], idx);
   12122                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12123                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12124                 :            :                                    NULL, "cannot create action");
   12125                 :          0 :                 return NULL;
   12126                 :            :         }
   12127                 :          0 :         return &entry->entry;
   12128                 :            : }
   12129                 :            : 
   12130                 :            : int
   12131                 :          0 : flow_dv_tag_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
   12132                 :            :                      void *cb_ctx)
   12133                 :            : {
   12134                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12135                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12136                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12137                 :            : 
   12138                 :          0 :         return *(uint32_t *)(ctx->data) != tag->tag_id;
   12139                 :            : }
   12140                 :            : 
   12141                 :            : struct mlx5_list_entry *
   12142                 :          0 : flow_dv_tag_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
   12143                 :            :                      void *cb_ctx)
   12144                 :            : {
   12145                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12146                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12147                 :            :         struct mlx5_flow_dv_tag_resource *entry;
   12148                 :          0 :         uint32_t idx = 0;
   12149                 :            : 
   12150                 :          0 :         entry = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_TAG], &idx);
   12151         [ #  # ]:          0 :         if (!entry) {
   12152                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12153                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12154                 :            :                                    "cannot allocate tag resource memory");
   12155                 :          0 :                 return NULL;
   12156                 :            :         }
   12157                 :            :         memcpy(entry, oentry, sizeof(*entry));
   12158                 :          0 :         entry->idx = idx;
   12159                 :          0 :         return &entry->entry;
   12160                 :            : }
   12161                 :            : 
   12162                 :            : void
   12163                 :          0 : flow_dv_tag_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   12164                 :            : {
   12165                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12166                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12167                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12168                 :            : 
   12169                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx);
   12170                 :          0 : }
   12171                 :            : 
   12172                 :            : /**
   12173                 :            :  * Find existing tag resource or create and register a new one.
   12174                 :            :  *
   12175                 :            :  * @param dev[in, out]
   12176                 :            :  *   Pointer to rte_eth_dev structure.
   12177                 :            :  * @param[in, out] tag_be24
   12178                 :            :  *   Tag value in big endian then R-shift 8.
   12179                 :            :  * @parm[in, out] dev_flow
   12180                 :            :  *   Pointer to the dev_flow.
   12181                 :            :  * @param[out] error
   12182                 :            :  *   pointer to error structure.
   12183                 :            :  *
   12184                 :            :  * @return
   12185                 :            :  *   0 on success otherwise -errno and errno is set.
   12186                 :            :  */
   12187                 :            : static int
   12188                 :          0 : flow_dv_tag_resource_register
   12189                 :            :                         (struct rte_eth_dev *dev,
   12190                 :            :                          uint32_t tag_be24,
   12191                 :            :                          struct mlx5_flow *dev_flow,
   12192                 :            :                          struct rte_flow_error *error)
   12193                 :            : {
   12194                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12195                 :            :         struct mlx5_flow_dv_tag_resource *resource;
   12196                 :            :         struct mlx5_list_entry *entry;
   12197                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12198                 :            :                                         .error = error,
   12199                 :            :                                         .data = &tag_be24,
   12200                 :            :                                         };
   12201                 :            :         struct mlx5_hlist *tag_table;
   12202                 :            : 
   12203                 :          0 :         tag_table = flow_dv_hlist_prepare(priv->sh, &priv->sh->tag_table,
   12204                 :            :                                       "tags",
   12205                 :            :                                       MLX5_TAGS_HLIST_ARRAY_SIZE,
   12206                 :          0 :                                       false, false, priv->sh,
   12207                 :            :                                       flow_dv_tag_create_cb,
   12208                 :            :                                       flow_dv_tag_match_cb,
   12209                 :            :                                       flow_dv_tag_remove_cb,
   12210                 :            :                                       flow_dv_tag_clone_cb,
   12211                 :            :                                       flow_dv_tag_clone_free_cb,
   12212                 :            :                                       error);
   12213         [ #  # ]:          0 :         if (unlikely(!tag_table))
   12214                 :          0 :                 return -rte_errno;
   12215                 :          0 :         entry = mlx5_hlist_register(tag_table, tag_be24, &ctx);
   12216         [ #  # ]:          0 :         if (entry) {
   12217                 :            :                 resource = container_of(entry, struct mlx5_flow_dv_tag_resource,
   12218                 :            :                                         entry);
   12219                 :          0 :                 dev_flow->handle->dvh.rix_tag = resource->idx;
   12220                 :          0 :                 dev_flow->dv.tag_resource = resource;
   12221                 :          0 :                 return 0;
   12222                 :            :         }
   12223                 :          0 :         return -rte_errno;
   12224                 :            : }
   12225                 :            : 
   12226                 :            : void
   12227                 :          0 : flow_dv_tag_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   12228                 :            : {
   12229                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12230                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12231                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12232                 :            : 
   12233                 :            :         MLX5_ASSERT(tag && sh && tag->action);
   12234                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(tag->action));
   12235                 :          0 :         DRV_LOG(DEBUG, "Tag %p: removed.", (void *)tag);
   12236                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx);
   12237                 :          0 : }
   12238                 :            : 
   12239                 :            : /**
   12240                 :            :  * Release the tag.
   12241                 :            :  *
   12242                 :            :  * @param dev
   12243                 :            :  *   Pointer to Ethernet device.
   12244                 :            :  * @param tag_idx
   12245                 :            :  *   Tag index.
   12246                 :            :  *
   12247                 :            :  * @return
   12248                 :            :  *   1 while a reference on it exists, 0 when freed.
   12249                 :            :  */
   12250                 :            : static int
   12251                 :          0 : flow_dv_tag_release(struct rte_eth_dev *dev,
   12252                 :            :                     uint32_t tag_idx)
   12253                 :            : {
   12254                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12255                 :            :         struct mlx5_flow_dv_tag_resource *tag;
   12256                 :            : 
   12257                 :          0 :         tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG], tag_idx);
   12258         [ #  # ]:          0 :         if (!tag)
   12259                 :            :                 return 0;
   12260                 :          0 :         DRV_LOG(DEBUG, "port %u tag %p: refcnt %d--",
   12261                 :            :                 dev->data->port_id, (void *)tag, tag->entry.ref_cnt);
   12262                 :          0 :         return mlx5_hlist_unregister(priv->sh->tag_table, &tag->entry);
   12263                 :            : }
   12264                 :            : 
   12265                 :            : /**
   12266                 :            :  * Translate action PORT_ID / REPRESENTED_PORT to vport.
   12267                 :            :  *
   12268                 :            :  * @param[in] dev
   12269                 :            :  *   Pointer to rte_eth_dev structure.
   12270                 :            :  * @param[in] action
   12271                 :            :  *   Pointer to action PORT_ID / REPRESENTED_PORT.
   12272                 :            :  * @param[out] dst_port_id
   12273                 :            :  *   The target port ID.
   12274                 :            :  * @param[out] error
   12275                 :            :  *   Pointer to the error structure.
   12276                 :            :  *
   12277                 :            :  * @return
   12278                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   12279                 :            :  */
   12280                 :            : static int
   12281                 :          0 : flow_dv_translate_action_port_id(struct rte_eth_dev *dev,
   12282                 :            :                                  const struct rte_flow_action *action,
   12283                 :            :                                  uint32_t *dst_port_id,
   12284                 :            :                                  struct rte_flow_error *error)
   12285                 :            : {
   12286                 :            :         uint32_t port;
   12287                 :            :         struct mlx5_priv *priv;
   12288                 :            : 
   12289      [ #  #  # ]:          0 :         switch (action->type) {
   12290                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID: {
   12291                 :            :                 const struct rte_flow_action_port_id *conf;
   12292                 :            : 
   12293                 :          0 :                 conf = (const struct rte_flow_action_port_id *)action->conf;
   12294         [ #  # ]:          0 :                 port = conf->original ? dev->data->port_id : conf->id;
   12295                 :            :                 break;
   12296                 :            :         }
   12297                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: {
   12298                 :            :                 const struct rte_flow_action_ethdev *ethdev;
   12299                 :            : 
   12300                 :          0 :                 ethdev = (const struct rte_flow_action_ethdev *)action->conf;
   12301                 :          0 :                 port = ethdev->port_id;
   12302                 :          0 :                 break;
   12303                 :            :         }
   12304                 :          0 :         default:
   12305                 :            :                 MLX5_ASSERT(false);
   12306                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12307                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
   12308                 :            :                                           "unknown E-Switch action");
   12309                 :            :         }
   12310                 :            : 
   12311                 :          0 :         priv = mlx5_port_to_eswitch_info(port, false);
   12312         [ #  # ]:          0 :         if (!priv)
   12313                 :          0 :                 return rte_flow_error_set(error, -rte_errno,
   12314                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   12315                 :            :                                           NULL,
   12316                 :            :                                           "No eswitch info was found for port");
   12317                 :            : #ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT
   12318                 :            :         /*
   12319                 :            :          * This parameter is transferred to
   12320                 :            :          * mlx5dv_dr_action_create_dest_ib_port().
   12321                 :            :          */
   12322                 :          0 :         *dst_port_id = priv->dev_port;
   12323                 :            : #else
   12324                 :            :         /*
   12325                 :            :          * Legacy mode, no LAG configurations is supported.
   12326                 :            :          * This parameter is transferred to
   12327                 :            :          * mlx5dv_dr_action_create_dest_vport().
   12328                 :            :          */
   12329                 :            :         *dst_port_id = priv->vport_id;
   12330                 :            : #endif
   12331                 :          0 :         return 0;
   12332                 :            : }
   12333                 :            : 
   12334                 :            : /**
   12335                 :            :  * Create a counter with aging configuration.
   12336                 :            :  *
   12337                 :            :  * @param[in] dev
   12338                 :            :  *   Pointer to rte_eth_dev structure.
   12339                 :            :  * @param[in] dev_flow
   12340                 :            :  *   Pointer to the mlx5_flow.
   12341                 :            :  * @param[out] count
   12342                 :            :  *   Pointer to the counter action configuration.
   12343                 :            :  * @param[in] age
   12344                 :            :  *   Pointer to the aging action configuration.
   12345                 :            :  *
   12346                 :            :  * @return
   12347                 :            :  *   Index to flow counter on success, 0 otherwise.
   12348                 :            :  */
   12349                 :            : static uint32_t
   12350                 :          0 : flow_dv_translate_create_counter(struct rte_eth_dev *dev,
   12351                 :            :                                 struct mlx5_flow *dev_flow,
   12352                 :            :                                 const struct rte_flow_action_count *count
   12353                 :            :                                         __rte_unused,
   12354                 :            :                                 const struct rte_flow_action_age *age)
   12355                 :            : {
   12356                 :            :         uint32_t counter;
   12357                 :            :         struct mlx5_age_param *age_param;
   12358                 :            : 
   12359                 :          0 :         counter = flow_dv_counter_alloc(dev, !!age);
   12360         [ #  # ]:          0 :         if (!counter || age == NULL)
   12361                 :            :                 return counter;
   12362                 :            :         age_param = flow_dv_counter_idx_get_age(dev, counter);
   12363         [ #  # ]:          0 :         age_param->context = age->context ? age->context :
   12364                 :          0 :                 (void *)(uintptr_t)(dev_flow->flow_idx);
   12365                 :          0 :         age_param->timeout = age->timeout;
   12366                 :          0 :         age_param->port_id = dev->data->port_id;
   12367                 :          0 :         rte_atomic_store_explicit(&age_param->sec_since_last_hit, 0, rte_memory_order_relaxed);
   12368                 :          0 :         rte_atomic_store_explicit(&age_param->state, AGE_CANDIDATE, rte_memory_order_relaxed);
   12369                 :          0 :         return counter;
   12370                 :            : }
   12371                 :            : 
   12372                 :            : /**
   12373                 :            :  * Add Tx queue matcher
   12374                 :            :  *
   12375                 :            :  * @param[in] dev
   12376                 :            :  *   Pointer to rte_eth_dev structure.
   12377                 :            :  * @param[in, out] key
   12378                 :            :  *   Flow matcher value.
   12379                 :            :  * @param[in] item
   12380                 :            :  *   Flow pattern to translate.
   12381                 :            :  * @param[in] key_type
   12382                 :            :  *   Set flow matcher mask or value.
   12383                 :            :  *
   12384                 :            :  * @return
   12385                 :            :  *   0 on success otherwise -errno and errno is set.
   12386                 :            :  */
   12387                 :            : static int
   12388                 :          0 : flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev, void *key,
   12389                 :            :                                 const struct rte_flow_item *item, uint32_t key_type)
   12390                 :            : {
   12391                 :            :         const struct rte_flow_item_tx_queue *queue_m;
   12392                 :            :         const struct rte_flow_item_tx_queue *queue_v;
   12393                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   12394                 :            :         uint32_t tx_queue;
   12395                 :            :         uint32_t sqn = 0;
   12396                 :            :         int ret;
   12397                 :            : 
   12398   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, queue_v, queue_m, &rte_flow_item_tx_queue_mask);
             #  #  #  # ]
   12399         [ #  # ]:          0 :         if (!queue_m || !queue_v)
   12400                 :            :                 return -EINVAL;
   12401         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_V) {
   12402                 :          0 :                 tx_queue = queue_v->tx_queue;
   12403         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_V)
   12404                 :          0 :                         tx_queue &= queue_m->tx_queue;
   12405         [ #  # ]:          0 :                 ret = flow_hw_get_sqn(dev, tx_queue, &sqn);
   12406         [ #  # ]:          0 :                 if (unlikely(ret))
   12407                 :          0 :                         return -ret;
   12408                 :            :         } else {
   12409                 :            :                 /* Due to tx_queue to sqn converting, only fully masked value support. */
   12410         [ #  # ]:          0 :                 if (queue_m->tx_queue != rte_flow_item_tx_queue_mask.tx_queue)
   12411                 :            :                         return -EINVAL;
   12412                 :            :                 sqn = UINT32_MAX;
   12413                 :            :         }
   12414         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_sqn, sqn);
   12415                 :          0 :         return 0;
   12416                 :            : }
   12417                 :            : 
   12418                 :            : /**
   12419                 :            :  * Add SQ matcher
   12420                 :            :  *
   12421                 :            :  * @param[in, out] matcher
   12422                 :            :  *   Flow matcher.
   12423                 :            :  * @param[in, out] key
   12424                 :            :  *   Flow matcher value.
   12425                 :            :  * @param[in] item
   12426                 :            :  *   Flow pattern to translate.
   12427                 :            :  * @param[in] key_type
   12428                 :            :  *   Set flow matcher mask or value.
   12429                 :            :  */
   12430                 :            : static void
   12431                 :          0 : flow_dv_translate_item_sq(void *key,
   12432                 :            :                           const struct rte_flow_item *item,
   12433                 :            :                           uint32_t key_type)
   12434                 :            : {
   12435                 :            :         const struct mlx5_rte_flow_item_sq *queue_m;
   12436                 :            :         const struct mlx5_rte_flow_item_sq *queue_v;
   12437                 :          0 :         const struct mlx5_rte_flow_item_sq queue_mask = {
   12438                 :            :                 .queue = UINT32_MAX,
   12439                 :            :         };
   12440                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   12441                 :            :         uint32_t queue;
   12442                 :            : 
   12443   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, queue_v, queue_m, &queue_mask);
             #  #  #  # ]
   12444         [ #  # ]:          0 :         if (!queue_m || !queue_v)
   12445                 :          0 :                 return;
   12446         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_V) {
   12447                 :          0 :                 queue = queue_v->queue;
   12448         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_V)
   12449                 :          0 :                         queue &= queue_m->queue;
   12450                 :            :         } else {
   12451                 :          0 :                 queue = queue_m->queue;
   12452                 :            :         }
   12453         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_sqn, queue);
   12454                 :            : }
   12455                 :            : 
   12456                 :            : /**
   12457                 :            :  * Set the hash fields according to the @p flow information.
   12458                 :            :  *
   12459                 :            :  * @param[in] item_flags
   12460                 :            :  *   The match pattern item flags.
   12461                 :            :  * @param[in] rss_desc
   12462                 :            :  *   Pointer to the mlx5_flow_rss_desc.
   12463                 :            :  * @param[out] hash_fields
   12464                 :            :  *   Pointer to the RSS hash fields.
   12465                 :            :  */
   12466                 :            : void
   12467                 :          0 : flow_dv_hashfields_set(uint64_t item_flags,
   12468                 :            :                        struct mlx5_flow_rss_desc *rss_desc,
   12469                 :            :                        uint64_t *hash_fields)
   12470                 :            : {
   12471                 :            :         uint64_t items = item_flags;
   12472                 :            :         uint64_t fields = 0;
   12473                 :            :         int rss_inner = 0;
   12474         [ #  # ]:          0 :         uint64_t rss_types = rte_eth_rss_hf_refine(rss_desc->types);
   12475                 :            : 
   12476                 :            :         *hash_fields = 0;
   12477                 :            : #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
   12478         [ #  # ]:          0 :         if (rss_desc->level >= 2)
   12479                 :            :                 rss_inner = 1;
   12480                 :            : #endif
   12481   [ #  #  #  # ]:          0 :         if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV4)) ||
   12482         [ #  # ]:          0 :             (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV4))) {
   12483         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV4_LAYER_TYPES) {
   12484         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   12485                 :            :                                 fields |= IBV_RX_HASH_SRC_IPV4;
   12486         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   12487                 :            :                                 fields |= IBV_RX_HASH_DST_IPV4;
   12488                 :            :                         else
   12489                 :            :                                 fields |= MLX5_IPV4_IBV_RX_HASH;
   12490                 :            :                 }
   12491   [ #  #  #  #  :          0 :         } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV6)) ||
                   #  # ]
   12492         [ #  # ]:          0 :                    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV6))) {
   12493         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV6_LAYER_TYPES) {
   12494         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   12495                 :            :                                 fields |= IBV_RX_HASH_SRC_IPV6;
   12496         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   12497                 :            :                                 fields |= IBV_RX_HASH_DST_IPV6;
   12498                 :            :                         else
   12499                 :            :                                 fields |= MLX5_IPV6_IBV_RX_HASH;
   12500                 :            :                 }
   12501                 :            :         }
   12502         [ #  # ]:          0 :         if (items & MLX5_FLOW_ITEM_ESP) {
   12503         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_ESP)
   12504                 :          0 :                         fields |= IBV_RX_HASH_IPSEC_SPI;
   12505                 :            :         }
   12506         [ #  # ]:          0 :         if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
   12507                 :          0 :                 *hash_fields = fields;
   12508                 :            :                 /*
   12509                 :            :                  * There is no match between the RSS types and the
   12510                 :            :                  * L3 protocol (IPv4/IPv6) defined in the flow rule.
   12511                 :            :                  */
   12512                 :          0 :                 return;
   12513                 :            :         }
   12514   [ #  #  #  #  :          0 :         if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
                   #  # ]
   12515         [ #  # ]:          0 :             (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP))) {
   12516         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_UDP) {
   12517         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   12518                 :          0 :                                 fields |= IBV_RX_HASH_SRC_PORT_UDP;
   12519         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   12520                 :          0 :                                 fields |= IBV_RX_HASH_DST_PORT_UDP;
   12521                 :            :                         else
   12522                 :          0 :                                 fields |= MLX5_UDP_IBV_RX_HASH;
   12523                 :            :                 }
   12524   [ #  #  #  #  :          0 :         } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_TCP)) ||
                   #  # ]
   12525         [ #  # ]:          0 :                    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_TCP))) {
   12526         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_TCP) {
   12527         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   12528                 :          0 :                                 fields |= IBV_RX_HASH_SRC_PORT_TCP;
   12529         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   12530                 :          0 :                                 fields |= IBV_RX_HASH_DST_PORT_TCP;
   12531                 :            :                         else
   12532                 :          0 :                                 fields |= MLX5_TCP_IBV_RX_HASH;
   12533                 :            :                 }
   12534                 :            :         }
   12535         [ #  # ]:          0 :         if (rss_inner)
   12536                 :          0 :                 fields |= IBV_RX_HASH_INNER;
   12537                 :          0 :         *hash_fields = fields;
   12538                 :            : }
   12539                 :            : 
   12540                 :            : /**
   12541                 :            :  * Prepare an Rx Hash queue.
   12542                 :            :  *
   12543                 :            :  * @param dev
   12544                 :            :  *   Pointer to Ethernet device.
   12545                 :            :  * @param[in] dev_flow
   12546                 :            :  *   Pointer to the mlx5_flow.
   12547                 :            :  * @param[in] rss_desc
   12548                 :            :  *   Pointer to the mlx5_flow_rss_desc.
   12549                 :            :  * @param[out] hrxq_idx
   12550                 :            :  *   Hash Rx queue index.
   12551                 :            :  *
   12552                 :            :  * @return
   12553                 :            :  *   The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.
   12554                 :            :  */
   12555                 :            : static struct mlx5_hrxq *
   12556                 :          0 : flow_dv_hrxq_prepare(struct rte_eth_dev *dev,
   12557                 :            :                      struct mlx5_flow *dev_flow,
   12558                 :            :                      struct mlx5_flow_rss_desc *rss_desc,
   12559                 :            :                      uint32_t *hrxq_idx)
   12560                 :            : {
   12561                 :          0 :         struct mlx5_flow_handle *dh = dev_flow->handle;
   12562                 :          0 :         uint32_t shared_rss = rss_desc->shared_rss;
   12563                 :            :         struct mlx5_hrxq *hrxq;
   12564                 :            : 
   12565                 :            :         MLX5_ASSERT(rss_desc->queue_num);
   12566                 :          0 :         rss_desc->symmetric_hash_function = dev_flow->symmetric_hash_function;
   12567                 :          0 :         rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN;
   12568                 :          0 :         rss_desc->hash_fields = dev_flow->hash_fields;
   12569                 :          0 :         rss_desc->tunnel = !!(dh->layers & MLX5_FLOW_LAYER_TUNNEL);
   12570                 :          0 :         rss_desc->shared_rss = 0;
   12571         [ #  # ]:          0 :         if (rss_desc->hash_fields == 0)
   12572                 :          0 :                 rss_desc->queue_num = 1;
   12573                 :          0 :         hrxq = mlx5_hrxq_get(dev, rss_desc);
   12574         [ #  # ]:          0 :         *hrxq_idx = hrxq ? hrxq->idx : 0;
   12575                 :          0 :         rss_desc->shared_rss = shared_rss;
   12576                 :          0 :         return hrxq;
   12577                 :            : }
   12578                 :            : 
   12579                 :            : /**
   12580                 :            :  * Release sample sub action resource.
   12581                 :            :  *
   12582                 :            :  * @param[in, out] dev
   12583                 :            :  *   Pointer to rte_eth_dev structure.
   12584                 :            :  * @param[in] act_res
   12585                 :            :  *   Pointer to sample sub action resource.
   12586                 :            :  */
   12587                 :            : static void
   12588                 :          0 : flow_dv_sample_sub_actions_release(struct rte_eth_dev *dev,
   12589                 :            :                                    struct mlx5_flow_sub_actions_idx *act_res)
   12590                 :            : {
   12591         [ #  # ]:          0 :         if (act_res->rix_hrxq) {
   12592                 :          0 :                 mlx5_hrxq_release(dev, act_res->rix_hrxq);
   12593                 :          0 :                 act_res->rix_hrxq = 0;
   12594                 :            :         }
   12595         [ #  # ]:          0 :         if (act_res->rix_encap_decap) {
   12596                 :          0 :                 flow_encap_decap_resource_release(dev,
   12597                 :            :                                                      act_res->rix_encap_decap);
   12598                 :          0 :                 act_res->rix_encap_decap = 0;
   12599                 :            :         }
   12600         [ #  # ]:          0 :         if (act_res->rix_port_id_action) {
   12601                 :          0 :                 flow_dv_port_id_action_resource_release(dev,
   12602                 :            :                                                 act_res->rix_port_id_action);
   12603                 :          0 :                 act_res->rix_port_id_action = 0;
   12604                 :            :         }
   12605         [ #  # ]:          0 :         if (act_res->rix_tag) {
   12606                 :          0 :                 flow_dv_tag_release(dev, act_res->rix_tag);
   12607                 :          0 :                 act_res->rix_tag = 0;
   12608                 :            :         }
   12609         [ #  # ]:          0 :         if (act_res->rix_jump) {
   12610                 :          0 :                 flow_dv_jump_tbl_resource_release(dev, act_res->rix_jump);
   12611                 :          0 :                 act_res->rix_jump = 0;
   12612                 :            :         }
   12613                 :          0 : }
   12614                 :            : 
   12615                 :            : int
   12616                 :          0 : flow_dv_sample_match_cb(void *tool_ctx __rte_unused,
   12617                 :            :                         struct mlx5_list_entry *entry, void *cb_ctx)
   12618                 :            : {
   12619                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12620                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12621                 :          0 :         struct mlx5_flow_dv_sample_resource *ctx_resource = ctx->data;
   12622                 :            :         struct mlx5_flow_dv_sample_resource *resource = container_of(entry,
   12623                 :            :                                                               typeof(*resource),
   12624                 :            :                                                               entry);
   12625                 :            : 
   12626         [ #  # ]:          0 :         if (ctx_resource->ratio == resource->ratio &&
   12627         [ #  # ]:          0 :             ctx_resource->ft_type == resource->ft_type &&
   12628         [ #  # ]:          0 :             ctx_resource->ft_id == resource->ft_id &&
   12629         [ #  # ]:          0 :             ctx_resource->set_action == resource->set_action &&
   12630                 :          0 :             !memcmp((void *)&ctx_resource->sample_act,
   12631         [ #  # ]:          0 :                     (void *)&resource->sample_act,
   12632                 :            :                     sizeof(struct mlx5_flow_sub_actions_list))) {
   12633                 :            :                 /*
   12634                 :            :                  * Existing sample action should release the prepared
   12635                 :            :                  * sub-actions reference counter.
   12636                 :            :                  */
   12637                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12638                 :            :                                                    &ctx_resource->sample_idx);
   12639                 :          0 :                 return 0;
   12640                 :            :         }
   12641                 :            :         return 1;
   12642                 :            : }
   12643                 :            : 
   12644                 :            : struct mlx5_list_entry *
   12645                 :          0 : flow_dv_sample_create_cb(void *tool_ctx __rte_unused, void *cb_ctx)
   12646                 :            : {
   12647                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12648                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12649                 :          0 :         struct mlx5_flow_dv_sample_resource *ctx_resource = ctx->data;
   12650                 :          0 :         void **sample_dv_actions = ctx_resource->sub_actions;
   12651                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12652                 :            :         struct mlx5dv_dr_flow_sampler_attr sampler_attr;
   12653                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12654                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12655                 :            :         struct mlx5_flow_tbl_resource *tbl;
   12656                 :          0 :         uint32_t idx = 0;
   12657                 :            :         const uint32_t next_ft_step = 1;
   12658                 :          0 :         uint32_t next_ft_id = ctx_resource->ft_id + next_ft_step;
   12659                 :            :         uint8_t is_egress = 0;
   12660                 :            :         uint8_t is_transfer = 0;
   12661                 :          0 :         struct rte_flow_error *error = ctx->error;
   12662                 :            : 
   12663                 :            :         /* Register new sample resource. */
   12664                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);
   12665         [ #  # ]:          0 :         if (!resource) {
   12666                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12667                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12668                 :            :                                           NULL,
   12669                 :            :                                           "cannot allocate resource memory");
   12670                 :          0 :                 return NULL;
   12671                 :            :         }
   12672                 :          0 :         *resource = *ctx_resource;
   12673                 :            :         /* Create normal path table level */
   12674         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
   12675                 :            :                 is_transfer = 1;
   12676         [ #  # ]:          0 :         else if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX)
   12677                 :            :                 is_egress = 1;
   12678                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, next_ft_id,
   12679                 :            :                                         is_egress, is_transfer,
   12680                 :            :                                         true, NULL, 0, 0, 0, error);
   12681         [ #  # ]:          0 :         if (!tbl) {
   12682                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12683                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12684                 :            :                                           NULL,
   12685                 :            :                                           "fail to create normal path table "
   12686                 :            :                                           "for sample");
   12687                 :          0 :                 goto error;
   12688                 :            :         }
   12689                 :          0 :         resource->normal_path_tbl = tbl;
   12690         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
   12691         [ #  # ]:          0 :                 if (!sh->default_miss_action) {
   12692                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   12693                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12694                 :            :                                                 NULL,
   12695                 :            :                                                 "default miss action was not "
   12696                 :            :                                                 "created");
   12697                 :          0 :                         goto error;
   12698                 :            :                 }
   12699                 :          0 :                 sample_dv_actions[ctx_resource->sample_act.actions_num++] =
   12700                 :            :                                                 sh->default_miss_action;
   12701                 :            :         }
   12702                 :            :         /* Create a DR sample action */
   12703                 :          0 :         sampler_attr.sample_ratio = resource->ratio;
   12704                 :          0 :         sampler_attr.default_next_table = tbl->obj;
   12705                 :          0 :         sampler_attr.num_sample_actions = ctx_resource->sample_act.actions_num;
   12706                 :          0 :         sampler_attr.sample_actions = (struct mlx5dv_dr_action **)
   12707                 :            :                                                         &sample_dv_actions[0];
   12708                 :          0 :         sampler_attr.action = resource->set_action;
   12709                 :            :         if (mlx5_os_flow_dr_create_flow_action_sampler
   12710                 :            :                         (&sampler_attr, &resource->verbs_action)) {
   12711                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12712                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12713                 :            :                                         NULL, "cannot create sample action");
   12714                 :          0 :                 goto error;
   12715                 :            :         }
   12716                 :          0 :         resource->idx = idx;
   12717                 :          0 :         resource->dev = dev;
   12718                 :          0 :         return &resource->entry;
   12719                 :          0 : error:
   12720         [ #  # ]:          0 :         if (resource->ft_type != MLX5DV_FLOW_TABLE_TYPE_FDB)
   12721                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12722                 :            :                                                    &resource->sample_idx);
   12723         [ #  # ]:          0 :         if (resource->normal_path_tbl)
   12724                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   12725                 :            :                                 resource->normal_path_tbl);
   12726                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE], idx);
   12727                 :          0 :         return NULL;
   12728                 :            : 
   12729                 :            : }
   12730                 :            : 
   12731                 :            : struct mlx5_list_entry *
   12732                 :          0 : flow_dv_sample_clone_cb(void *tool_ctx __rte_unused,
   12733                 :            :                          struct mlx5_list_entry *entry __rte_unused,
   12734                 :            :                          void *cb_ctx)
   12735                 :            : {
   12736                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12737                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12738                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12739                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12740                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12741                 :          0 :         uint32_t idx = 0;
   12742                 :            : 
   12743                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);
   12744         [ #  # ]:          0 :         if (!resource) {
   12745                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12746                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12747                 :            :                                           NULL,
   12748                 :            :                                           "cannot allocate resource memory");
   12749                 :          0 :                 return NULL;
   12750                 :            :         }
   12751                 :            :         memcpy(resource, entry, sizeof(*resource));
   12752                 :          0 :         resource->idx = idx;
   12753                 :          0 :         resource->dev = dev;
   12754                 :          0 :         return &resource->entry;
   12755                 :            : }
   12756                 :            : 
   12757                 :            : void
   12758                 :          0 : flow_dv_sample_clone_free_cb(void *tool_ctx __rte_unused,
   12759                 :            :                              struct mlx5_list_entry *entry)
   12760                 :            : {
   12761                 :            :         struct mlx5_flow_dv_sample_resource *resource =
   12762                 :            :                                   container_of(entry, typeof(*resource), entry);
   12763                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   12764                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12765                 :            : 
   12766                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], resource->idx);
   12767                 :          0 : }
   12768                 :            : 
   12769                 :            : /**
   12770                 :            :  * Find existing sample resource or create and register a new one.
   12771                 :            :  *
   12772                 :            :  * @param[in, out] dev
   12773                 :            :  *   Pointer to rte_eth_dev structure.
   12774                 :            :  * @param[in] ref
   12775                 :            :  *   Pointer to sample resource reference.
   12776                 :            :  * @parm[in, out] dev_flow
   12777                 :            :  *   Pointer to the dev_flow.
   12778                 :            :  * @param[out] error
   12779                 :            :  *   pointer to error structure.
   12780                 :            :  *
   12781                 :            :  * @return
   12782                 :            :  *   0 on success otherwise -errno and errno is set.
   12783                 :            :  */
   12784                 :            : static int
   12785                 :          0 : flow_dv_sample_resource_register(struct rte_eth_dev *dev,
   12786                 :            :                          struct mlx5_flow_dv_sample_resource *ref,
   12787                 :            :                          struct mlx5_flow *dev_flow,
   12788                 :            :                          struct rte_flow_error *error)
   12789                 :            : {
   12790                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12791                 :            :         struct mlx5_list_entry *entry;
   12792                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12793                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12794                 :            :                 .dev = dev,
   12795                 :            :                 .error = error,
   12796                 :            :                 .data = ref,
   12797                 :            :         };
   12798                 :            : 
   12799                 :          0 :         entry = mlx5_list_register(priv->sh->sample_action_list, &ctx);
   12800         [ #  # ]:          0 :         if (!entry)
   12801                 :          0 :                 return -rte_errno;
   12802                 :            :         resource = container_of(entry, typeof(*resource), entry);
   12803                 :          0 :         dev_flow->handle->dvh.rix_sample = resource->idx;
   12804                 :          0 :         dev_flow->dv.sample_res = resource;
   12805                 :          0 :         return 0;
   12806                 :            : }
   12807                 :            : 
   12808                 :            : int
   12809                 :          0 : flow_dv_dest_array_match_cb(void *tool_ctx __rte_unused,
   12810                 :            :                             struct mlx5_list_entry *entry, void *cb_ctx)
   12811                 :            : {
   12812                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12813                 :          0 :         struct mlx5_flow_dv_dest_array_resource *ctx_resource = ctx->data;
   12814                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12815                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   12816                 :            :                                   container_of(entry, typeof(*resource), entry);
   12817                 :            :         uint32_t idx = 0;
   12818                 :            : 
   12819         [ #  # ]:          0 :         if (ctx_resource->num_of_dest == resource->num_of_dest &&
   12820                 :          0 :             ctx_resource->ft_type == resource->ft_type &&
   12821                 :          0 :             !memcmp((void *)resource->sample_act,
   12822                 :          0 :                     (void *)ctx_resource->sample_act,
   12823         [ #  # ]:          0 :                    (ctx_resource->num_of_dest *
   12824                 :            :                    sizeof(struct mlx5_flow_sub_actions_list)))) {
   12825                 :            :                 /*
   12826                 :            :                  * Existing sample action should release the prepared
   12827                 :            :                  * sub-actions reference counter.
   12828                 :            :                  */
   12829         [ #  # ]:          0 :                 for (idx = 0; idx < ctx_resource->num_of_dest; idx++)
   12830                 :          0 :                         flow_dv_sample_sub_actions_release(dev,
   12831                 :            :                                         &ctx_resource->sample_idx[idx]);
   12832                 :            :                 return 0;
   12833                 :            :         }
   12834                 :            :         return 1;
   12835                 :            : }
   12836                 :            : 
   12837                 :            : struct mlx5_list_entry *
   12838                 :          0 : flow_dv_dest_array_create_cb(void *tool_ctx __rte_unused, void *cb_ctx)
   12839                 :            : {
   12840                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12841                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12842                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12843                 :          0 :         struct mlx5_flow_dv_dest_array_resource *ctx_resource = ctx->data;
   12844                 :          0 :         struct mlx5dv_dr_action_dest_attr *dest_attr[MLX5_MAX_DEST_NUM] = { 0 };
   12845                 :            :         struct mlx5dv_dr_action_dest_reformat dest_reformat[MLX5_MAX_DEST_NUM];
   12846                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12847                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12848                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   12849                 :            :         struct mlx5dv_dr_domain *domain;
   12850                 :          0 :         uint32_t idx = 0, res_idx = 0;
   12851                 :          0 :         struct rte_flow_error *error = ctx->error;
   12852                 :            :         uint64_t action_flags;
   12853                 :            :         int ret;
   12854                 :            : 
   12855                 :            :         /* Register new destination array resource. */
   12856                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   12857                 :            :                                             &res_idx);
   12858         [ #  # ]:          0 :         if (!resource) {
   12859                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12860                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12861                 :            :                                           NULL,
   12862                 :            :                                           "cannot allocate resource memory");
   12863                 :          0 :                 return NULL;
   12864                 :            :         }
   12865                 :          0 :         *resource = *ctx_resource;
   12866         [ #  # ]:          0 :         if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
   12867                 :          0 :                 domain = sh->fdb_domain;
   12868         [ #  # ]:          0 :         else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
   12869                 :          0 :                 domain = sh->rx_domain;
   12870                 :            :         else
   12871                 :          0 :                 domain = sh->tx_domain;
   12872         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++) {
   12873                 :          0 :                 dest_attr[idx] = (struct mlx5dv_dr_action_dest_attr *)
   12874                 :          0 :                                  mlx5_malloc(MLX5_MEM_ZERO,
   12875                 :            :                                  sizeof(struct mlx5dv_dr_action_dest_attr),
   12876                 :            :                                  0, SOCKET_ID_ANY);
   12877         [ #  # ]:          0 :                 if (!dest_attr[idx]) {
   12878                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   12879                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12880                 :            :                                            NULL,
   12881                 :            :                                            "cannot allocate resource memory");
   12882                 :          0 :                         goto error;
   12883                 :            :                 }
   12884                 :          0 :                 dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST;
   12885                 :            :                 sample_act = &ctx_resource->sample_act[idx];
   12886                 :          0 :                 action_flags = sample_act->action_flags;
   12887   [ #  #  #  #  :          0 :                 switch (action_flags) {
                      # ]
   12888                 :          0 :                 case MLX5_FLOW_ACTION_QUEUE:
   12889                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_queue_action;
   12890                 :          0 :                         break;
   12891                 :          0 :                 case (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP):
   12892                 :          0 :                         dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT;
   12893                 :          0 :                         dest_attr[idx]->dest_reformat = &dest_reformat[idx];
   12894                 :          0 :                         dest_attr[idx]->dest_reformat->reformat =
   12895                 :          0 :                                         sample_act->dr_encap_action;
   12896                 :          0 :                         dest_attr[idx]->dest_reformat->dest =
   12897                 :          0 :                                         sample_act->dr_port_id_action;
   12898                 :          0 :                         break;
   12899                 :          0 :                 case MLX5_FLOW_ACTION_PORT_ID:
   12900                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_port_id_action;
   12901                 :          0 :                         break;
   12902                 :          0 :                 case MLX5_FLOW_ACTION_JUMP:
   12903                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_jump_action;
   12904                 :          0 :                         break;
   12905                 :          0 :                 default:
   12906                 :          0 :                         rte_flow_error_set(error, EINVAL,
   12907                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   12908                 :            :                                            NULL,
   12909                 :            :                                            "unsupported actions type");
   12910                 :          0 :                         goto error;
   12911                 :            :                 }
   12912                 :            :         }
   12913                 :            :         /* create a dest array action */
   12914                 :          0 :         ret = mlx5_os_flow_dr_create_flow_action_dest_array
   12915                 :            :                                                 (domain,
   12916                 :          0 :                                                  resource->num_of_dest,
   12917                 :            :                                                  dest_attr,
   12918                 :            :                                                  &resource->action);
   12919                 :            :         if (ret) {
   12920                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12921                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12922                 :            :                                    NULL,
   12923                 :            :                                    "cannot create destination array action");
   12924                 :          0 :                 goto error;
   12925                 :            :         }
   12926                 :          0 :         resource->idx = res_idx;
   12927                 :          0 :         resource->dev = dev;
   12928         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++)
   12929                 :          0 :                 mlx5_free(dest_attr[idx]);
   12930                 :          0 :         return &resource->entry;
   12931                 :            : error:
   12932         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++) {
   12933                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12934                 :            :                                                    &resource->sample_idx[idx]);
   12935         [ #  # ]:          0 :                 if (dest_attr[idx])
   12936                 :          0 :                         mlx5_free(dest_attr[idx]);
   12937                 :            :         }
   12938                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY], res_idx);
   12939                 :          0 :         return NULL;
   12940                 :            : }
   12941                 :            : 
   12942                 :            : struct mlx5_list_entry *
   12943                 :          0 : flow_dv_dest_array_clone_cb(void *tool_ctx __rte_unused,
   12944                 :            :                             struct mlx5_list_entry *entry __rte_unused,
   12945                 :            :                             void *cb_ctx)
   12946                 :            : {
   12947                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12948                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12949                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12950                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12951                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12952                 :          0 :         uint32_t res_idx = 0;
   12953                 :          0 :         struct rte_flow_error *error = ctx->error;
   12954                 :            : 
   12955                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   12956                 :            :                                       &res_idx);
   12957         [ #  # ]:          0 :         if (!resource) {
   12958                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12959                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12960                 :            :                                           NULL,
   12961                 :            :                                           "cannot allocate dest-array memory");
   12962                 :          0 :                 return NULL;
   12963                 :            :         }
   12964                 :            :         memcpy(resource, entry, sizeof(*resource));
   12965                 :          0 :         resource->idx = res_idx;
   12966                 :          0 :         resource->dev = dev;
   12967                 :          0 :         return &resource->entry;
   12968                 :            : }
   12969                 :            : 
   12970                 :            : void
   12971                 :          0 : flow_dv_dest_array_clone_free_cb(void *tool_ctx __rte_unused,
   12972                 :            :                                  struct mlx5_list_entry *entry)
   12973                 :            : {
   12974                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   12975                 :            :                         container_of(entry, typeof(*resource), entry);
   12976                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   12977                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12978                 :            : 
   12979                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], resource->idx);
   12980                 :          0 : }
   12981                 :            : 
   12982                 :            : /**
   12983                 :            :  * Find existing destination array resource or create and register a new one.
   12984                 :            :  *
   12985                 :            :  * @param[in, out] dev
   12986                 :            :  *   Pointer to rte_eth_dev structure.
   12987                 :            :  * @param[in] ref
   12988                 :            :  *   Pointer to destination array resource reference.
   12989                 :            :  * @parm[in, out] dev_flow
   12990                 :            :  *   Pointer to the dev_flow.
   12991                 :            :  * @param[out] error
   12992                 :            :  *   pointer to error structure.
   12993                 :            :  *
   12994                 :            :  * @return
   12995                 :            :  *   0 on success otherwise -errno and errno is set.
   12996                 :            :  */
   12997                 :            : static int
   12998                 :          0 : flow_dv_dest_array_resource_register(struct rte_eth_dev *dev,
   12999                 :            :                          struct mlx5_flow_dv_dest_array_resource *ref,
   13000                 :            :                          struct mlx5_flow *dev_flow,
   13001                 :            :                          struct rte_flow_error *error)
   13002                 :            : {
   13003                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   13004                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13005                 :            :         struct mlx5_list_entry *entry;
   13006                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   13007                 :            :                 .dev = dev,
   13008                 :            :                 .error = error,
   13009                 :            :                 .data = ref,
   13010                 :            :         };
   13011                 :            : 
   13012                 :          0 :         entry = mlx5_list_register(priv->sh->dest_array_list, &ctx);
   13013         [ #  # ]:          0 :         if (!entry)
   13014                 :          0 :                 return -rte_errno;
   13015                 :            :         resource = container_of(entry, typeof(*resource), entry);
   13016                 :          0 :         dev_flow->handle->dvh.rix_dest_array = resource->idx;
   13017                 :          0 :         dev_flow->dv.dest_array_res = resource;
   13018                 :          0 :         return 0;
   13019                 :            : }
   13020                 :            : 
   13021                 :            : /**
   13022                 :            :  * Convert Sample action to DV specification.
   13023                 :            :  *
   13024                 :            :  * @param[in] dev
   13025                 :            :  *   Pointer to rte_eth_dev structure.
   13026                 :            :  * @param[in] action
   13027                 :            :  *   Pointer to sample action structure.
   13028                 :            :  * @param[in, out] dev_flow
   13029                 :            :  *   Pointer to the mlx5_flow.
   13030                 :            :  * @param[in] attr
   13031                 :            :  *   Pointer to the flow attributes.
   13032                 :            :  * @param[in, out] num_of_dest
   13033                 :            :  *   Pointer to the num of destination.
   13034                 :            :  * @param[in, out] sample_actions
   13035                 :            :  *   Pointer to sample actions list.
   13036                 :            :  * @param[in, out] res
   13037                 :            :  *   Pointer to sample resource.
   13038                 :            :  * @param[out] error
   13039                 :            :  *   Pointer to the error structure.
   13040                 :            :  *
   13041                 :            :  * @return
   13042                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13043                 :            :  */
   13044                 :            : static int
   13045                 :          0 : flow_dv_translate_action_sample(struct rte_eth_dev *dev,
   13046                 :            :                                 const struct rte_flow_action_sample *action,
   13047                 :            :                                 struct mlx5_flow *dev_flow,
   13048                 :            :                                 const struct rte_flow_attr *attr,
   13049                 :            :                                 uint32_t *num_of_dest,
   13050                 :            :                                 void **sample_actions,
   13051                 :            :                                 struct mlx5_flow_dv_sample_resource *res,
   13052                 :            :                                 struct rte_flow_error *error)
   13053                 :            : {
   13054                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13055                 :            :         const struct rte_flow_action *sub_actions;
   13056                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   13057                 :            :         struct mlx5_flow_sub_actions_idx *sample_idx;
   13058                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   13059                 :          0 :         struct rte_flow *flow = dev_flow->flow;
   13060                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   13061                 :            :         uint64_t action_flags = 0;
   13062                 :            : 
   13063                 :            :         MLX5_ASSERT(wks);
   13064                 :          0 :         rss_desc = &wks->rss_desc;
   13065                 :            :         sample_act = &res->sample_act;
   13066                 :            :         sample_idx = &res->sample_idx;
   13067                 :          0 :         res->ratio = action->ratio;
   13068                 :          0 :         sub_actions = action->actions;
   13069         [ #  # ]:          0 :         for (; sub_actions->type != RTE_FLOW_ACTION_TYPE_END; sub_actions++) {
   13070                 :            :                 int type = sub_actions->type;
   13071                 :            :                 uint32_t pre_rix = 0;
   13072                 :            :                 void *pre_r;
   13073   [ #  #  #  #  :          0 :                 switch (type) {
                #  #  # ]
   13074                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   13075                 :            :                 {
   13076                 :            :                         const struct rte_flow_action_queue *queue;
   13077                 :            :                         struct mlx5_hrxq *hrxq;
   13078                 :            :                         uint32_t hrxq_idx;
   13079                 :            : 
   13080                 :          0 :                         queue = sub_actions->conf;
   13081                 :          0 :                         rss_desc->queue_num = 1;
   13082                 :          0 :                         rss_desc->queue[0] = queue->index;
   13083                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13084                 :            :                                                     rss_desc, &hrxq_idx);
   13085         [ #  # ]:          0 :                         if (!hrxq)
   13086                 :          0 :                                 return rte_flow_error_set
   13087                 :            :                                         (error, rte_errno,
   13088                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   13089                 :            :                                          NULL,
   13090                 :            :                                          "cannot create fate queue");
   13091                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13092                 :          0 :                         sample_idx->rix_hrxq = hrxq_idx;
   13093                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13094                 :            :                                                 hrxq->action;
   13095                 :          0 :                         (*num_of_dest)++;
   13096                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
   13097         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13098                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13099                 :          0 :                         dev_flow->handle->fate_action =
   13100                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   13101                 :          0 :                         break;
   13102                 :            :                 }
   13103                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   13104                 :            :                 {
   13105                 :            :                         struct mlx5_hrxq *hrxq;
   13106                 :            :                         uint32_t hrxq_idx;
   13107                 :            :                         const struct rte_flow_action_rss *rss;
   13108                 :            :                         const uint8_t *rss_key;
   13109                 :            : 
   13110                 :          0 :                         rss = sub_actions->conf;
   13111                 :          0 :                         rss_desc->symmetric_hash_function =
   13112                 :          0 :                                 MLX5_RSS_IS_SYMM(rss->func);
   13113                 :          0 :                         memcpy(rss_desc->queue, rss->queue,
   13114         [ #  # ]:          0 :                                rss->queue_num * sizeof(uint16_t));
   13115                 :          0 :                         rss_desc->queue_num = rss->queue_num;
   13116                 :            :                         /* NULL RSS key indicates default RSS key. */
   13117         [ #  # ]:          0 :                         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   13118                 :          0 :                         memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   13119                 :            :                         /*
   13120                 :            :                          * rss->level and rss.types should be set in advance
   13121                 :            :                          * when expanding items for RSS.
   13122                 :            :                          */
   13123                 :          0 :                         flow_dv_hashfields_set(dev_flow->handle->layers,
   13124                 :            :                                                rss_desc,
   13125                 :            :                                                &dev_flow->hash_fields);
   13126                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13127                 :            :                                                     rss_desc, &hrxq_idx);
   13128         [ #  # ]:          0 :                         if (!hrxq)
   13129                 :          0 :                                 return rte_flow_error_set
   13130                 :            :                                         (error, rte_errno,
   13131                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   13132                 :            :                                          NULL,
   13133                 :            :                                          "cannot create fate queue");
   13134                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13135                 :          0 :                         sample_idx->rix_hrxq = hrxq_idx;
   13136                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13137                 :            :                                                 hrxq->action;
   13138                 :          0 :                         (*num_of_dest)++;
   13139                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
   13140         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13141                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13142                 :          0 :                         dev_flow->handle->fate_action =
   13143                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   13144                 :          0 :                         break;
   13145                 :            :                 }
   13146                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
   13147                 :            :                 {
   13148                 :            :                         uint32_t tag_be = mlx5_flow_mark_set
   13149                 :            :                                 (((const struct rte_flow_action_mark *)
   13150         [ #  # ]:          0 :                                 (sub_actions->conf))->id);
   13151                 :            : 
   13152                 :          0 :                         wks->mark = 1;
   13153                 :          0 :                         pre_rix = dev_flow->handle->dvh.rix_tag;
   13154                 :            :                         /* Save the mark resource before sample */
   13155                 :          0 :                         pre_r = dev_flow->dv.tag_resource;
   13156         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   13157                 :            :                                                   dev_flow, error))
   13158                 :          0 :                                 return -rte_errno;
   13159                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   13160                 :          0 :                         sample_act->dr_tag_action =
   13161                 :          0 :                                 dev_flow->dv.tag_resource->action;
   13162                 :          0 :                         sample_idx->rix_tag =
   13163                 :          0 :                                 dev_flow->handle->dvh.rix_tag;
   13164                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13165                 :            :                                                 sample_act->dr_tag_action;
   13166                 :            :                         /* Recover the mark resource after sample */
   13167                 :          0 :                         dev_flow->dv.tag_resource = pre_r;
   13168                 :          0 :                         dev_flow->handle->dvh.rix_tag = pre_rix;
   13169                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
   13170                 :          0 :                         break;
   13171                 :            :                 }
   13172                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   13173                 :            :                 {
   13174         [ #  # ]:          0 :                         if (!flow->counter) {
   13175                 :          0 :                                 flow->counter =
   13176                 :          0 :                                         flow_dv_translate_create_counter(dev,
   13177                 :          0 :                                                 dev_flow, sub_actions->conf,
   13178                 :            :                                                 0);
   13179         [ #  # ]:          0 :                                 if (!flow->counter)
   13180                 :          0 :                                         return rte_flow_error_set
   13181                 :            :                                                 (error, rte_errno,
   13182                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   13183                 :            :                                                 NULL,
   13184                 :            :                                                 "cannot create counter"
   13185                 :            :                                                 " object.");
   13186                 :            :                         }
   13187                 :          0 :                         sample_act->dr_cnt_action =
   13188         [ #  # ]:          0 :                                   (flow_dv_counter_get_by_idx(dev,
   13189                 :          0 :                                   flow->counter, NULL))->action;
   13190                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13191                 :            :                                                 sample_act->dr_cnt_action;
   13192                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
   13193                 :          0 :                         break;
   13194                 :            :                 }
   13195                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
   13196                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   13197                 :            :                 {
   13198                 :            :                         struct mlx5_flow_dv_port_id_action_resource
   13199                 :            :                                         port_id_resource;
   13200                 :          0 :                         uint32_t port_id = 0;
   13201                 :            : 
   13202                 :            :                         memset(&port_id_resource, 0, sizeof(port_id_resource));
   13203                 :            :                         /* Save the port id resource before sample */
   13204                 :          0 :                         pre_rix = dev_flow->handle->rix_port_id_action;
   13205                 :          0 :                         pre_r = dev_flow->dv.port_id_action;
   13206         [ #  # ]:          0 :                         if (flow_dv_translate_action_port_id(dev, sub_actions,
   13207                 :            :                                                              &port_id, error))
   13208                 :          0 :                                 return -rte_errno;
   13209                 :          0 :                         port_id_resource.port_id = port_id;
   13210         [ #  # ]:          0 :                         if (flow_dv_port_id_action_resource_register
   13211                 :            :                             (dev, &port_id_resource, dev_flow, error))
   13212                 :          0 :                                 return -rte_errno;
   13213                 :          0 :                         sample_act->dr_port_id_action =
   13214                 :          0 :                                 dev_flow->dv.port_id_action->action;
   13215                 :          0 :                         sample_idx->rix_port_id_action =
   13216                 :          0 :                                 dev_flow->handle->rix_port_id_action;
   13217                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13218                 :            :                                                 sample_act->dr_port_id_action;
   13219                 :            :                         /* Recover the port id resource after sample */
   13220                 :          0 :                         dev_flow->dv.port_id_action = pre_r;
   13221                 :          0 :                         dev_flow->handle->rix_port_id_action = pre_rix;
   13222                 :          0 :                         (*num_of_dest)++;
   13223                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   13224                 :          0 :                         break;
   13225                 :            :                 }
   13226                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   13227                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   13228                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   13229                 :            :                         /* Save the encap resource before sample */
   13230                 :          0 :                         pre_rix = dev_flow->handle->dvh.rix_encap_decap;
   13231                 :          0 :                         pre_r = dev_flow->dv.encap_decap;
   13232         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_encap(dev, sub_actions,
   13233                 :            :                                                            dev_flow,
   13234                 :          0 :                                                            attr->transfer,
   13235                 :            :                                                            error))
   13236                 :          0 :                                 return -rte_errno;
   13237                 :          0 :                         sample_act->dr_encap_action =
   13238                 :          0 :                                 dev_flow->dv.encap_decap->action;
   13239                 :          0 :                         sample_idx->rix_encap_decap =
   13240                 :          0 :                                 dev_flow->handle->dvh.rix_encap_decap;
   13241                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13242                 :            :                                                 sample_act->dr_encap_action;
   13243                 :            :                         /* Recover the encap resource after sample */
   13244                 :          0 :                         dev_flow->dv.encap_decap = pre_r;
   13245                 :          0 :                         dev_flow->handle->dvh.rix_encap_decap = pre_rix;
   13246                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   13247                 :          0 :                         break;
   13248                 :          0 :                 default:
   13249                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13250                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13251                 :            :                                 NULL,
   13252                 :            :                                 "Not support for sampler action");
   13253                 :            :                 }
   13254                 :            :         }
   13255                 :          0 :         sample_act->action_flags = action_flags;
   13256                 :          0 :         res->ft_id = dev_flow->dv.group;
   13257         [ #  # ]:          0 :         if (attr->transfer) {
   13258                 :            :                 union {
   13259                 :            :                         uint32_t action_in[MLX5_ST_SZ_DW(set_action_in)];
   13260                 :            :                         uint64_t set_action;
   13261                 :            :                 } action_ctx = { .set_action = 0 };
   13262                 :          0 :                 uint32_t vport_meta_tag = wks->vport_meta_tag ?
   13263         [ #  # ]:          0 :                                           wks->vport_meta_tag :
   13264                 :            :                                           priv->vport_meta_tag;
   13265                 :            : 
   13266                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
   13267                 :            :                 MLX5_SET(set_action_in, action_ctx.action_in, action_type,
   13268                 :            :                          MLX5_MODIFICATION_TYPE_SET);
   13269         [ #  # ]:          0 :                 MLX5_SET(set_action_in, action_ctx.action_in, field,
   13270                 :            :                          MLX5_MODI_META_REG_C_0);
   13271                 :          0 :                 MLX5_SET(set_action_in, action_ctx.action_in, data,
   13272                 :            :                          vport_meta_tag);
   13273                 :          0 :                 res->set_action = action_ctx.set_action;
   13274         [ #  # ]:          0 :         } else if (attr->ingress) {
   13275                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   13276                 :            :         } else {
   13277                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX;
   13278                 :            :         }
   13279                 :            :         return 0;
   13280                 :            : }
   13281                 :            : 
   13282                 :            : static void *
   13283                 :          0 : flow_dv_translate_action_send_to_kernel(struct rte_eth_dev *dev,
   13284                 :            :                                         const struct rte_flow_attr *attr,
   13285                 :            :                                         struct rte_flow_error *error)
   13286                 :            : {
   13287                 :            :         struct mlx5_flow_tbl_resource *tbl;
   13288                 :            :         struct mlx5_dev_ctx_shared *sh;
   13289                 :            :         uint32_t priority;
   13290                 :            :         void *action;
   13291                 :            :         int ft_type;
   13292                 :            :         int ret;
   13293                 :            : 
   13294                 :          0 :         sh = MLX5_SH(dev);
   13295         [ #  # ]:          0 :         ft_type = (attr->ingress) ? MLX5DR_TABLE_TYPE_NIC_RX :
   13296         [ #  # ]:          0 :                   ((attr->transfer) ? MLX5DR_TABLE_TYPE_FDB :
   13297                 :            :                   MLX5DR_TABLE_TYPE_NIC_TX);
   13298         [ #  # ]:          0 :         if (sh->send_to_kernel_action[ft_type].action)
   13299                 :            :                 return sh->send_to_kernel_action[ft_type].action;
   13300                 :          0 :         priority = mlx5_get_send_to_kernel_priority(dev);
   13301         [ #  # ]:          0 :         if (priority == (uint32_t)-1) {
   13302                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   13303                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13304                 :            :                                    "required priority is not available");
   13305                 :          0 :                 return NULL;
   13306                 :            :         }
   13307                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, attr->egress, attr->transfer, false, NULL, 0, 0, 0,
   13308                 :            :                                        error);
   13309         [ #  # ]:          0 :         if (!tbl) {
   13310                 :          0 :                 rte_flow_error_set(error, ENODATA,
   13311                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13312                 :            :                                    "cannot find destination root table");
   13313                 :          0 :                 return NULL;
   13314                 :            :         }
   13315                 :          0 :         ret = mlx5_flow_os_create_flow_action_send_to_kernel(tbl->obj,
   13316                 :            :                                 priority, &action);
   13317                 :            :         if (ret) {
   13318                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   13319                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13320                 :            :                                    "cannot create action");
   13321                 :          0 :                 goto err;
   13322                 :            :         }
   13323                 :            :         MLX5_ASSERT(action);
   13324                 :          0 :         sh->send_to_kernel_action[ft_type].action = action;
   13325                 :          0 :         sh->send_to_kernel_action[ft_type].tbl = tbl;
   13326                 :          0 :         return action;
   13327                 :            : err:
   13328                 :          0 :         flow_dv_tbl_resource_release(sh, tbl);
   13329                 :          0 :         return NULL;
   13330                 :            : }
   13331                 :            : 
   13332                 :            : /**
   13333                 :            :  * Convert Sample action to DV specification.
   13334                 :            :  *
   13335                 :            :  * @param[in] dev
   13336                 :            :  *   Pointer to rte_eth_dev structure.
   13337                 :            :  * @param[in, out] dev_flow
   13338                 :            :  *   Pointer to the mlx5_flow.
   13339                 :            :  * @param[in] num_of_dest
   13340                 :            :  *   The num of destination.
   13341                 :            :  * @param[in, out] res
   13342                 :            :  *   Pointer to sample resource.
   13343                 :            :  * @param[in, out] mdest_res
   13344                 :            :  *   Pointer to destination array resource.
   13345                 :            :  * @param[in] sample_actions
   13346                 :            :  *   Pointer to sample path actions list.
   13347                 :            :  * @param[in] action_flags
   13348                 :            :  *   Holds the actions detected until now.
   13349                 :            :  * @param[out] error
   13350                 :            :  *   Pointer to the error structure.
   13351                 :            :  *
   13352                 :            :  * @return
   13353                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13354                 :            :  */
   13355                 :            : static int
   13356                 :          0 : flow_dv_create_action_sample(struct rte_eth_dev *dev,
   13357                 :            :                              struct mlx5_flow *dev_flow,
   13358                 :            :                              uint32_t num_of_dest,
   13359                 :            :                              struct mlx5_flow_dv_sample_resource *res,
   13360                 :            :                              struct mlx5_flow_dv_dest_array_resource *mdest_res,
   13361                 :            :                              void **sample_actions,
   13362                 :            :                              uint64_t action_flags,
   13363                 :            :                              struct rte_flow_error *error)
   13364                 :            : {
   13365                 :            :         /* update normal path action resource into last index of array */
   13366                 :            :         uint32_t dest_index = MLX5_MAX_DEST_NUM - 1;
   13367                 :            :         struct mlx5_flow_sub_actions_list *sample_act =
   13368                 :            :                                         &mdest_res->sample_act[dest_index];
   13369                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   13370                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   13371                 :            :         uint32_t normal_idx = 0;
   13372                 :            :         struct mlx5_hrxq *hrxq;
   13373                 :            :         uint32_t hrxq_idx;
   13374                 :            : 
   13375                 :            :         MLX5_ASSERT(wks);
   13376                 :          0 :         rss_desc = &wks->rss_desc;
   13377         [ #  # ]:          0 :         if (num_of_dest > 1) {
   13378         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_QUEUE) {
   13379                 :            :                         /* Handle QP action for mirroring */
   13380                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13381                 :            :                                                     rss_desc, &hrxq_idx);
   13382         [ #  # ]:          0 :                         if (!hrxq)
   13383                 :          0 :                                 return rte_flow_error_set
   13384                 :            :                                      (error, rte_errno,
   13385                 :            :                                       RTE_FLOW_ERROR_TYPE_ACTION,
   13386                 :            :                                       NULL,
   13387                 :            :                                       "cannot create rx queue");
   13388                 :            :                         normal_idx++;
   13389                 :          0 :                         mdest_res->sample_idx[dest_index].rix_hrxq = hrxq_idx;
   13390                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13391         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13392                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13393                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
   13394                 :            :                 }
   13395         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_ENCAP) {
   13396                 :          0 :                         normal_idx++;
   13397                 :          0 :                         mdest_res->sample_idx[dest_index].rix_encap_decap =
   13398                 :          0 :                                 dev_flow->handle->dvh.rix_encap_decap;
   13399                 :          0 :                         sample_act->dr_encap_action =
   13400                 :          0 :                                 dev_flow->dv.encap_decap->action;
   13401                 :          0 :                         dev_flow->handle->dvh.rix_encap_decap = 0;
   13402                 :            :                 }
   13403         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_PORT_ID) {
   13404                 :          0 :                         normal_idx++;
   13405                 :          0 :                         mdest_res->sample_idx[dest_index].rix_port_id_action =
   13406                 :          0 :                                 dev_flow->handle->rix_port_id_action;
   13407                 :          0 :                         sample_act->dr_port_id_action =
   13408                 :          0 :                                 dev_flow->dv.port_id_action->action;
   13409                 :          0 :                         dev_flow->handle->rix_port_id_action = 0;
   13410                 :            :                 }
   13411         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_JUMP) {
   13412                 :          0 :                         normal_idx++;
   13413                 :          0 :                         mdest_res->sample_idx[dest_index].rix_jump =
   13414                 :          0 :                                 dev_flow->handle->rix_jump;
   13415                 :          0 :                         sample_act->dr_jump_action =
   13416                 :          0 :                                 dev_flow->dv.jump->action;
   13417                 :          0 :                         dev_flow->handle->rix_jump = 0;
   13418                 :            :                 }
   13419                 :          0 :                 sample_act->actions_num = normal_idx;
   13420                 :            :                 /* update sample action resource into first index of array */
   13421                 :          0 :                 mdest_res->ft_type = res->ft_type;
   13422                 :          0 :                 memcpy(&mdest_res->sample_idx[0], &res->sample_idx,
   13423                 :            :                                 sizeof(struct mlx5_flow_sub_actions_idx));
   13424                 :          0 :                 memcpy(&mdest_res->sample_act[0], &res->sample_act,
   13425                 :            :                                 sizeof(struct mlx5_flow_sub_actions_list));
   13426                 :          0 :                 mdest_res->num_of_dest = num_of_dest;
   13427         [ #  # ]:          0 :                 if (flow_dv_dest_array_resource_register(dev, mdest_res,
   13428                 :            :                                                          dev_flow, error))
   13429                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13430                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   13431                 :            :                                                   NULL, "can't create sample "
   13432                 :            :                                                   "action");
   13433                 :            :         } else {
   13434                 :          0 :                 res->sub_actions = sample_actions;
   13435         [ #  # ]:          0 :                 if (flow_dv_sample_resource_register(dev, res, dev_flow, error))
   13436                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13437                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   13438                 :            :                                                   NULL,
   13439                 :            :                                                   "can't create sample action");
   13440                 :            :         }
   13441                 :            :         return 0;
   13442                 :            : }
   13443                 :            : 
   13444                 :            : /**
   13445                 :            :  * Remove an ASO age action from age actions list.
   13446                 :            :  *
   13447                 :            :  * @param[in] dev
   13448                 :            :  *   Pointer to the Ethernet device structure.
   13449                 :            :  * @param[in] age
   13450                 :            :  *   Pointer to the aso age action handler.
   13451                 :            :  */
   13452                 :            : static void
   13453                 :          0 : flow_dv_aso_age_remove_from_age(struct rte_eth_dev *dev,
   13454                 :            :                                 struct mlx5_aso_age_action *age)
   13455                 :            : {
   13456                 :            :         struct mlx5_age_info *age_info;
   13457                 :            :         struct mlx5_age_param *age_param = &age->age_params;
   13458                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13459                 :            :         uint16_t expected = AGE_CANDIDATE;
   13460                 :            : 
   13461                 :          0 :         age_info = GET_PORT_AGE_INFO(priv);
   13462         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&age_param->state, &expected,
   13463                 :            :                                          AGE_FREE, rte_memory_order_relaxed,
   13464                 :            :                                          rte_memory_order_relaxed)) {
   13465                 :            :                 /**
   13466                 :            :                  * We need the lock even it is age timeout,
   13467                 :            :                  * since age action may still in process.
   13468                 :            :                  */
   13469                 :          0 :                 rte_spinlock_lock(&age_info->aged_sl);
   13470         [ #  # ]:          0 :                 LIST_REMOVE(age, next);
   13471                 :            :                 rte_spinlock_unlock(&age_info->aged_sl);
   13472                 :          0 :                 rte_atomic_store_explicit(&age_param->state, AGE_FREE, rte_memory_order_relaxed);
   13473                 :            :         }
   13474                 :          0 : }
   13475                 :            : 
   13476                 :            : /**
   13477                 :            :  * Release an ASO age action.
   13478                 :            :  *
   13479                 :            :  * @param[in] dev
   13480                 :            :  *   Pointer to the Ethernet device structure.
   13481                 :            :  * @param[in] age_idx
   13482                 :            :  *   Index of ASO age action to release.
   13483                 :            :  * @param[in] flow
   13484                 :            :  *   True if the release operation is during flow destroy operation.
   13485                 :            :  *   False if the release operation is during action destroy operation.
   13486                 :            :  *
   13487                 :            :  * @return
   13488                 :            :  *   0 when age action was removed, otherwise the number of references.
   13489                 :            :  */
   13490                 :            : static int
   13491                 :          0 : flow_dv_aso_age_release(struct rte_eth_dev *dev, uint32_t age_idx)
   13492                 :            : {
   13493                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13494                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13495                 :          0 :         struct mlx5_aso_age_action *age = flow_aso_age_get_by_idx(dev, age_idx);
   13496                 :          0 :         uint32_t ret = rte_atomic_fetch_sub_explicit(&age->refcnt, 1, rte_memory_order_relaxed) - 1;
   13497                 :            : 
   13498         [ #  # ]:          0 :         if (!ret) {
   13499                 :          0 :                 flow_dv_aso_age_remove_from_age(dev, age);
   13500                 :          0 :                 rte_spinlock_lock(&mng->free_sl);
   13501         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free, age, next);
   13502                 :            :                 rte_spinlock_unlock(&mng->free_sl);
   13503                 :            :         }
   13504                 :          0 :         return ret;
   13505                 :            : }
   13506                 :            : 
   13507                 :            : /**
   13508                 :            :  * Resize the ASO age pools array by MLX5_ASO_AGE_CONTAINER_RESIZE pools.
   13509                 :            :  *
   13510                 :            :  * @param[in] dev
   13511                 :            :  *   Pointer to the Ethernet device structure.
   13512                 :            :  *
   13513                 :            :  * @return
   13514                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
   13515                 :            :  */
   13516                 :            : static int
   13517                 :          0 : flow_dv_aso_age_pools_resize(struct rte_eth_dev *dev)
   13518                 :            : {
   13519                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13520                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13521                 :          0 :         void *old_pools = mng->pools;
   13522                 :          0 :         uint32_t resize = mng->n + MLX5_ASO_AGE_CONTAINER_RESIZE;
   13523                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_age_pool *) * resize;
   13524                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   13525                 :            : 
   13526         [ #  # ]:          0 :         if (!pools) {
   13527                 :          0 :                 rte_errno = ENOMEM;
   13528                 :          0 :                 return -ENOMEM;
   13529                 :            :         }
   13530         [ #  # ]:          0 :         if (old_pools) {
   13531                 :          0 :                 memcpy(pools, old_pools,
   13532                 :          0 :                        mng->n * sizeof(struct mlx5_flow_counter_pool *));
   13533                 :          0 :                 mlx5_free(old_pools);
   13534                 :            :         } else {
   13535                 :            :                 /* First ASO flow hit allocation - starting ASO data-path. */
   13536                 :          0 :                 int ret = mlx5_aso_flow_hit_queue_poll_start(priv->sh);
   13537                 :            : 
   13538         [ #  # ]:          0 :                 if (ret) {
   13539                 :          0 :                         mlx5_free(pools);
   13540                 :          0 :                         return ret;
   13541                 :            :                 }
   13542                 :            :         }
   13543                 :          0 :         mng->n = resize;
   13544                 :          0 :         mng->pools = pools;
   13545                 :          0 :         return 0;
   13546                 :            : }
   13547                 :            : 
   13548                 :            : /**
   13549                 :            :  * Create and initialize a new ASO aging pool.
   13550                 :            :  *
   13551                 :            :  * @param[in] dev
   13552                 :            :  *   Pointer to the Ethernet device structure.
   13553                 :            :  * @param[out] age_free
   13554                 :            :  *   Where to put the pointer of a new age action.
   13555                 :            :  *
   13556                 :            :  * @return
   13557                 :            :  *   The age actions pool pointer and @p age_free is set on success,
   13558                 :            :  *   NULL otherwise and rte_errno is set.
   13559                 :            :  */
   13560                 :            : static struct mlx5_aso_age_pool *
   13561                 :          0 : flow_dv_age_pool_create(struct rte_eth_dev *dev,
   13562                 :            :                         struct mlx5_aso_age_action **age_free)
   13563                 :            : {
   13564                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13565                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13566                 :            :         struct mlx5_aso_age_pool *pool = NULL;
   13567                 :            :         struct mlx5_devx_obj *obj = NULL;
   13568                 :            :         uint32_t i;
   13569                 :            : 
   13570                 :          0 :         obj = mlx5_devx_cmd_create_flow_hit_aso_obj(priv->sh->cdev->ctx,
   13571                 :          0 :                                                     priv->sh->cdev->pdn);
   13572         [ #  # ]:          0 :         if (!obj) {
   13573                 :          0 :                 rte_errno = ENODATA;
   13574                 :          0 :                 DRV_LOG(ERR, "Failed to create flow_hit_aso_obj using DevX.");
   13575                 :          0 :                 return NULL;
   13576                 :            :         }
   13577                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY);
   13578         [ #  # ]:          0 :         if (!pool) {
   13579                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13580                 :          0 :                 rte_errno = ENOMEM;
   13581                 :          0 :                 return NULL;
   13582                 :            :         }
   13583                 :          0 :         pool->flow_hit_aso_obj = obj;
   13584                 :          0 :         pool->time_of_last_age_check = MLX5_CURR_TIME_SEC;
   13585                 :          0 :         rte_rwlock_write_lock(&mng->resize_rwl);
   13586                 :          0 :         pool->index = mng->next;
   13587                 :            :         /* Resize pools array if there is no room for the new pool in it. */
   13588   [ #  #  #  # ]:          0 :         if (pool->index == mng->n && flow_dv_aso_age_pools_resize(dev)) {
   13589                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13590                 :          0 :                 mlx5_free(pool);
   13591                 :            :                 rte_rwlock_write_unlock(&mng->resize_rwl);
   13592                 :          0 :                 return NULL;
   13593                 :            :         }
   13594                 :          0 :         mng->pools[pool->index] = pool;
   13595                 :          0 :         mng->next++;
   13596                 :            :         rte_rwlock_write_unlock(&mng->resize_rwl);
   13597                 :            :         /* Assign the first action in the new pool, the rest go to free list. */
   13598                 :          0 :         *age_free = &pool->actions[0];
   13599         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_AGE_ACTIONS_PER_POOL; i++) {
   13600                 :          0 :                 pool->actions[i].offset = i;
   13601         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free, &pool->actions[i], next);
   13602                 :            :         }
   13603                 :            :         return pool;
   13604                 :            : }
   13605                 :            : 
   13606                 :            : /**
   13607                 :            :  * Allocate a ASO aging bit.
   13608                 :            :  *
   13609                 :            :  * @param[in] dev
   13610                 :            :  *   Pointer to the Ethernet device structure.
   13611                 :            :  * @param[out] error
   13612                 :            :  *   Pointer to the error structure.
   13613                 :            :  *
   13614                 :            :  * @return
   13615                 :            :  *   Index to ASO age action on success, 0 otherwise and rte_errno is set.
   13616                 :            :  */
   13617                 :            : static uint32_t
   13618                 :          0 : flow_dv_aso_age_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error)
   13619                 :            : {
   13620                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13621                 :            :         const struct mlx5_aso_age_pool *pool;
   13622                 :          0 :         struct mlx5_aso_age_action *age_free = NULL;
   13623                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13624                 :            : 
   13625                 :            :         MLX5_ASSERT(mng);
   13626                 :            :         /* Try to get the next free age action bit. */
   13627                 :          0 :         rte_spinlock_lock(&mng->free_sl);
   13628                 :          0 :         age_free = LIST_FIRST(&mng->free);
   13629         [ #  # ]:          0 :         if (age_free) {
   13630         [ #  # ]:          0 :                 LIST_REMOVE(age_free, next);
   13631         [ #  # ]:          0 :         } else if (!flow_dv_age_pool_create(dev, &age_free)) {
   13632                 :            :                 rte_spinlock_unlock(&mng->free_sl);
   13633                 :          0 :                 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
   13634                 :            :                                    NULL, "failed to create ASO age pool");
   13635                 :          0 :                 return 0; /* 0 is an error. */
   13636                 :            :         }
   13637                 :            :         rte_spinlock_unlock(&mng->free_sl);
   13638                 :          0 :         pool = container_of
   13639                 :            :           ((const struct mlx5_aso_age_action (*)[MLX5_ASO_AGE_ACTIONS_PER_POOL])
   13640                 :            :                   (age_free - age_free->offset), const struct mlx5_aso_age_pool,
   13641                 :            :                                                                        actions);
   13642         [ #  # ]:          0 :         if (!age_free->dr_action) {
   13643                 :          0 :                 int reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_FLOW_HIT, 0,
   13644                 :            :                                                  error);
   13645                 :            : 
   13646         [ #  # ]:          0 :                 if (reg_c < 0) {
   13647                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13648                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   13649                 :            :                                            NULL, "failed to get reg_c "
   13650                 :            :                                            "for ASO flow hit");
   13651                 :          0 :                         return 0; /* 0 is an error. */
   13652                 :            :                 }
   13653                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
   13654                 :          0 :                 age_free->dr_action = mlx5_glue->dv_create_flow_action_aso
   13655                 :          0 :                                 (priv->sh->rx_domain,
   13656                 :          0 :                                  pool->flow_hit_aso_obj->obj, age_free->offset,
   13657                 :            :                                  MLX5DV_DR_ACTION_FLAGS_ASO_FIRST_HIT_SET,
   13658                 :          0 :                                  (reg_c - REG_C_0));
   13659                 :            : #endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
   13660         [ #  # ]:          0 :                 if (!age_free->dr_action) {
   13661                 :          0 :                         rte_errno = errno;
   13662                 :            :                         rte_spinlock_lock(&mng->free_sl);
   13663         [ #  # ]:          0 :                         LIST_INSERT_HEAD(&mng->free, age_free, next);
   13664                 :            :                         rte_spinlock_unlock(&mng->free_sl);
   13665                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13666                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   13667                 :            :                                            NULL, "failed to create ASO "
   13668                 :            :                                            "flow hit action");
   13669                 :          0 :                         return 0; /* 0 is an error. */
   13670                 :            :                 }
   13671                 :            :         }
   13672                 :          0 :         rte_atomic_store_explicit(&age_free->refcnt, 1, rte_memory_order_relaxed);
   13673                 :          0 :         return pool->index | ((age_free->offset + 1) << 16);
   13674                 :            : }
   13675                 :            : 
   13676                 :            : /**
   13677                 :            :  * Initialize flow ASO age parameters.
   13678                 :            :  *
   13679                 :            :  * @param[in] dev
   13680                 :            :  *   Pointer to rte_eth_dev structure.
   13681                 :            :  * @param[in] age_idx
   13682                 :            :  *   Index of ASO age action.
   13683                 :            :  * @param[in] context
   13684                 :            :  *   Pointer to flow counter age context.
   13685                 :            :  * @param[in] timeout
   13686                 :            :  *   Aging timeout in seconds.
   13687                 :            :  *
   13688                 :            :  */
   13689                 :            : static void
   13690                 :          0 : flow_dv_aso_age_params_init(struct rte_eth_dev *dev,
   13691                 :            :                             uint32_t age_idx,
   13692                 :            :                             void *context,
   13693                 :            :                             uint32_t timeout)
   13694                 :            : {
   13695                 :            :         struct mlx5_aso_age_action *aso_age;
   13696                 :            : 
   13697                 :          0 :         aso_age = flow_aso_age_get_by_idx(dev, age_idx);
   13698                 :            :         MLX5_ASSERT(aso_age);
   13699                 :          0 :         aso_age->age_params.context = context;
   13700                 :          0 :         aso_age->age_params.timeout = timeout;
   13701                 :          0 :         aso_age->age_params.port_id = dev->data->port_id;
   13702                 :          0 :         rte_atomic_store_explicit(&aso_age->age_params.sec_since_last_hit, 0,
   13703                 :            :                          rte_memory_order_relaxed);
   13704                 :          0 :         rte_atomic_store_explicit(&aso_age->age_params.state, AGE_CANDIDATE,
   13705                 :            :                          rte_memory_order_relaxed);
   13706                 :          0 : }
   13707                 :            : 
   13708                 :            : static void
   13709                 :          0 : flow_dv_translate_integrity_l4(const struct rte_flow_item_integrity *mask,
   13710                 :            :                                void *headers)
   13711                 :            : {
   13712                 :            :         /*
   13713                 :            :          * In HWS mode MLX5_ITEM_UPDATE() macro assigns the same pointer to
   13714                 :            :          * both mask and value, therefore ether can be used.
   13715                 :            :          * In SWS SW_V mode mask points to item mask and value points to item
   13716                 :            :          * spec. Integrity item value is used only if matching mask is set.
   13717                 :            :          * Use mask reference here to keep SWS functionality.
   13718                 :            :          */
   13719         [ #  # ]:          0 :         if (mask->l4_ok) {
   13720                 :            :                 /* RTE l4_ok filter aggregates hardware l4_ok and
   13721                 :            :                  * l4_checksum_ok filters.
   13722                 :            :                  * Positive RTE l4_ok match requires hardware match on both L4
   13723                 :            :                  * hardware integrity bits.
   13724                 :            :                  * PMD supports positive integrity item semantics only.
   13725                 :            :                  */
   13726         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_ok, 1);
   13727         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_checksum_ok, 1);
   13728         [ #  # ]:          0 :         } else if (mask->l4_csum_ok) {
   13729         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_checksum_ok, 1);
   13730                 :            :         }
   13731                 :          0 : }
   13732                 :            : 
   13733                 :            : static void
   13734                 :          0 : flow_dv_translate_integrity_l3(const struct rte_flow_item_integrity *mask,
   13735                 :            :                                void *headers, bool is_ipv4)
   13736                 :            : {
   13737                 :            :         /*
   13738                 :            :          * In HWS mode MLX5_ITEM_UPDATE() macro assigns the same pointer to
   13739                 :            :          * both mask and value, therefore ether can be used.
   13740                 :            :          * In SWS SW_V mode mask points to item mask and value points to item
   13741                 :            :          * spec. Integrity item value used only if matching mask is set.
   13742                 :            :          * Use mask reference here to keep SWS functionality.
   13743                 :            :          */
   13744         [ #  # ]:          0 :         if (mask->l3_ok) {
   13745                 :            :                 /* RTE l3_ok filter aggregates for IPv4 hardware l3_ok and
   13746                 :            :                  * ipv4_csum_ok filters.
   13747                 :            :                  * Positive RTE l3_ok match requires hardware match on both L3
   13748                 :            :                  * hardware integrity bits.
   13749                 :            :                  * PMD supports positive integrity item semantics only.
   13750                 :            :                  */
   13751         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l3_ok, 1);
   13752         [ #  # ]:          0 :                 if (is_ipv4) {
   13753         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers,
   13754                 :            :                                  ipv4_checksum_ok, 1);
   13755                 :            :                 }
   13756   [ #  #  #  # ]:          0 :         } else if (is_ipv4 && mask->ipv4_csum_ok) {
   13757         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, ipv4_checksum_ok, 1);
   13758                 :            :         }
   13759                 :          0 : }
   13760                 :            : 
   13761                 :            : static void
   13762                 :          0 : set_integrity_bits(void *headers, const struct rte_flow_item *integrity_item,
   13763                 :            :                    bool is_l3_ip4, uint32_t key_type)
   13764                 :            : {
   13765                 :            :         const struct rte_flow_item_integrity *spec;
   13766                 :            :         const struct rte_flow_item_integrity *mask;
   13767                 :            : 
   13768                 :            :         /* Integrity bits validation cleared spec pointer */
   13769   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(integrity_item, key_type))
          #  #  #  #  #  
                      # ]
   13770                 :            :                 return;
   13771   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(integrity_item, key_type, spec, mask,
             #  #  #  # ]
   13772                 :            :                          &rte_flow_item_integrity_mask);
   13773                 :          0 :         flow_dv_translate_integrity_l3(mask, headers, is_l3_ip4);
   13774                 :          0 :         flow_dv_translate_integrity_l4(mask, headers);
   13775                 :            : }
   13776                 :            : 
   13777                 :            : static void
   13778                 :          0 : flow_dv_translate_item_integrity_post(void *key,
   13779                 :            :                                       const
   13780                 :            :                                       struct rte_flow_item *integrity_items[2],
   13781                 :            :                                       uint64_t pattern_flags, uint32_t key_type)
   13782                 :            : {
   13783                 :            :         void *headers;
   13784                 :            :         bool is_l3_ip4;
   13785                 :            : 
   13786         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY) {
   13787                 :          0 :                 headers = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
   13788                 :          0 :                 is_l3_ip4 = (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV4) !=
   13789                 :            :                             0;
   13790                 :          0 :                 set_integrity_bits(headers, integrity_items[1], is_l3_ip4,
   13791                 :            :                                    key_type);
   13792                 :            :         }
   13793         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY) {
   13794                 :            :                 headers = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   13795                 :          0 :                 is_l3_ip4 = (pattern_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4) !=
   13796                 :            :                             0;
   13797                 :          0 :                 set_integrity_bits(headers, integrity_items[0], is_l3_ip4,
   13798                 :            :                                    key_type);
   13799                 :            :         }
   13800                 :          0 : }
   13801                 :            : 
   13802                 :            : static uint64_t
   13803                 :            : flow_dv_translate_item_integrity(const struct rte_flow_item *item,
   13804                 :            :                                  struct mlx5_dv_matcher_workspace *wks,
   13805                 :            :                                  uint64_t key_type)
   13806                 :            : {
   13807                 :          0 :         if ((key_type & MLX5_SET_MATCHER_SW) != 0) {
   13808                 :            :                 const struct rte_flow_item_integrity
   13809                 :          0 :                         *spec = (typeof(spec))item->spec;
   13810                 :            : 
   13811                 :            :                 /* SWS integrity bits validation cleared spec pointer */
   13812         [ #  # ]:          0 :                 if (spec->level > 1) {
   13813                 :          0 :                         wks->integrity_items[1] = item;
   13814                 :          0 :                         wks->last_item |= MLX5_FLOW_ITEM_INNER_INTEGRITY;
   13815                 :            :                 } else {
   13816                 :          0 :                         wks->integrity_items[0] = item;
   13817                 :          0 :                         wks->last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
   13818                 :            :                 }
   13819                 :            :         } else {
   13820                 :            :                 /* HWS supports outer integrity only */
   13821                 :          0 :                 wks->integrity_items[0] = item;
   13822                 :          0 :                 wks->last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
   13823                 :            :         }
   13824                 :          0 :         return wks->last_item;
   13825                 :            : }
   13826                 :            : 
   13827                 :            : /**
   13828                 :            :  * Prepares DV flow counter with aging configuration.
   13829                 :            :  * Gets it by index when exists, creates a new one when doesn't.
   13830                 :            :  *
   13831                 :            :  * @param[in] dev
   13832                 :            :  *   Pointer to rte_eth_dev structure.
   13833                 :            :  * @param[in] dev_flow
   13834                 :            :  *   Pointer to the mlx5_flow.
   13835                 :            :  * @param[in, out] flow
   13836                 :            :  *   Pointer to the sub flow.
   13837                 :            :  * @param[in] count
   13838                 :            :  *   Pointer to the counter action configuration.
   13839                 :            :  * @param[in] age
   13840                 :            :  *   Pointer to the aging action configuration.
   13841                 :            :  * @param[out] error
   13842                 :            :  *   Pointer to the error structure.
   13843                 :            :  *
   13844                 :            :  * @return
   13845                 :            :  *   Pointer to the counter, NULL otherwise.
   13846                 :            :  */
   13847                 :            : static struct mlx5_flow_counter *
   13848                 :          0 : flow_dv_prepare_counter(struct rte_eth_dev *dev,
   13849                 :            :                         struct mlx5_flow *dev_flow,
   13850                 :            :                         struct rte_flow *flow,
   13851                 :            :                         const struct rte_flow_action_count *count,
   13852                 :            :                         const struct rte_flow_action_age *age,
   13853                 :            :                         struct rte_flow_error *error)
   13854                 :            : {
   13855         [ #  # ]:          0 :         if (!flow->counter) {
   13856                 :          0 :                 flow->counter = flow_dv_translate_create_counter(dev, dev_flow,
   13857                 :            :                                                                  count, age);
   13858         [ #  # ]:          0 :                 if (!flow->counter) {
   13859                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13860                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13861                 :            :                                            "cannot create counter object.");
   13862                 :          0 :                         return NULL;
   13863                 :            :                 }
   13864                 :            :         }
   13865         [ #  # ]:          0 :         return flow_dv_counter_get_by_idx(dev, flow->counter, NULL);
   13866                 :            : }
   13867                 :            : 
   13868                 :            : /*
   13869                 :            :  * Release an ASO CT action by its own device.
   13870                 :            :  *
   13871                 :            :  * @param[in] dev
   13872                 :            :  *   Pointer to the Ethernet device structure.
   13873                 :            :  * @param[in] idx
   13874                 :            :  *   Index of ASO CT action to release.
   13875                 :            :  *
   13876                 :            :  * @return
   13877                 :            :  *   0 when CT action was removed, otherwise the number of references.
   13878                 :            :  */
   13879                 :            : static inline int
   13880                 :          0 : flow_dv_aso_ct_dev_release(struct rte_eth_dev *dev, uint32_t idx)
   13881                 :            : {
   13882                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13883                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13884                 :            :         uint32_t ret;
   13885                 :          0 :         struct mlx5_aso_ct_action *ct = flow_aso_ct_get_by_dev_idx(dev, idx);
   13886                 :            :         enum mlx5_aso_ct_state state =
   13887                 :          0 :                         rte_atomic_load_explicit(&ct->state, rte_memory_order_relaxed);
   13888                 :            : 
   13889                 :            :         /* Cannot release when CT is in the ASO SQ. */
   13890         [ #  # ]:          0 :         if (state == ASO_CONNTRACK_WAIT || state == ASO_CONNTRACK_QUERY)
   13891                 :            :                 return -1;
   13892                 :          0 :         ret = rte_atomic_fetch_sub_explicit(&ct->refcnt, 1, rte_memory_order_relaxed) - 1;
   13893         [ #  # ]:          0 :         if (!ret) {
   13894         [ #  # ]:          0 :                 if (ct->dr_action_orig) {
   13895                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13896                 :          0 :                         claim_zero(mlx5_glue->destroy_flow_action
   13897                 :            :                                         (ct->dr_action_orig));
   13898                 :            : #endif
   13899                 :          0 :                         ct->dr_action_orig = NULL;
   13900                 :            :                 }
   13901         [ #  # ]:          0 :                 if (ct->dr_action_rply) {
   13902                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13903                 :          0 :                         claim_zero(mlx5_glue->destroy_flow_action
   13904                 :            :                                         (ct->dr_action_rply));
   13905                 :            : #endif
   13906                 :          0 :                         ct->dr_action_rply = NULL;
   13907                 :            :                 }
   13908                 :            :                 /* Clear the state to free, no need in 1st allocation. */
   13909                 :          0 :                 MLX5_ASO_CT_UPDATE_STATE(ct, ASO_CONNTRACK_FREE);
   13910                 :          0 :                 rte_spinlock_lock(&mng->ct_sl);
   13911         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free_cts, ct, next);
   13912                 :            :                 rte_spinlock_unlock(&mng->ct_sl);
   13913                 :            :         }
   13914                 :          0 :         return (int)ret;
   13915                 :            : }
   13916                 :            : 
   13917                 :            : static inline int
   13918                 :          0 : flow_dv_aso_ct_release(struct rte_eth_dev *dev, uint32_t own_idx,
   13919                 :            :                        struct rte_flow_error *error)
   13920                 :            : {
   13921                 :          0 :         uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(own_idx);
   13922                 :          0 :         uint32_t idx = MLX5_INDIRECT_ACT_CT_GET_IDX(own_idx);
   13923                 :          0 :         struct rte_eth_dev *owndev = &rte_eth_devices[owner];
   13924                 :            :         int ret;
   13925                 :            : 
   13926                 :            :         MLX5_ASSERT(owner < RTE_MAX_ETHPORTS);
   13927         [ #  # ]:          0 :         if (dev->data->dev_started != 1)
   13928                 :          0 :                 return rte_flow_error_set(error, EAGAIN,
   13929                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   13930                 :            :                                           NULL,
   13931                 :            :                                           "Indirect CT action cannot be destroyed when the port is stopped");
   13932                 :          0 :         ret = flow_dv_aso_ct_dev_release(owndev, idx);
   13933         [ #  # ]:          0 :         if (ret < 0)
   13934                 :          0 :                 return rte_flow_error_set(error, EAGAIN,
   13935                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   13936                 :            :                                           NULL,
   13937                 :            :                                           "Current state prevents indirect CT action from being destroyed");
   13938                 :            :         return ret;
   13939                 :            : }
   13940                 :            : 
   13941                 :            : /*
   13942                 :            :  * Resize the ASO CT pools array by 64 pools.
   13943                 :            :  *
   13944                 :            :  * @param[in] dev
   13945                 :            :  *   Pointer to the Ethernet device structure.
   13946                 :            :  *
   13947                 :            :  * @return
   13948                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
   13949                 :            :  */
   13950                 :            : static int
   13951                 :          0 : flow_dv_aso_ct_pools_resize(struct rte_eth_dev *dev)
   13952                 :            : {
   13953                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13954                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13955                 :          0 :         void *old_pools = mng->pools;
   13956                 :            :         /* Magic number now, need a macro. */
   13957                 :          0 :         uint32_t resize = mng->n + 64;
   13958                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_ct_pool *) * resize;
   13959                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   13960                 :            : 
   13961         [ #  # ]:          0 :         if (!pools) {
   13962                 :          0 :                 rte_errno = ENOMEM;
   13963                 :          0 :                 return -rte_errno;
   13964                 :            :         }
   13965                 :          0 :         rte_rwlock_write_lock(&mng->resize_rwl);
   13966                 :            :         /* ASO SQ/QP was already initialized in the startup. */
   13967         [ #  # ]:          0 :         if (old_pools) {
   13968                 :            :                 /* Realloc could be an alternative choice. */
   13969                 :          0 :                 rte_memcpy(pools, old_pools,
   13970         [ #  # ]:          0 :                            mng->n * sizeof(struct mlx5_aso_ct_pool *));
   13971                 :          0 :                 mlx5_free(old_pools);
   13972                 :            :         }
   13973                 :          0 :         mng->n = resize;
   13974                 :          0 :         mng->pools = pools;
   13975                 :            :         rte_rwlock_write_unlock(&mng->resize_rwl);
   13976                 :          0 :         return 0;
   13977                 :            : }
   13978                 :            : 
   13979                 :            : /*
   13980                 :            :  * Create and initialize a new ASO CT pool.
   13981                 :            :  *
   13982                 :            :  * @param[in] dev
   13983                 :            :  *   Pointer to the Ethernet device structure.
   13984                 :            :  * @param[out] ct_free
   13985                 :            :  *   Where to put the pointer of a new CT action.
   13986                 :            :  *
   13987                 :            :  * @return
   13988                 :            :  *   The CT actions pool pointer and @p ct_free is set on success,
   13989                 :            :  *   NULL otherwise and rte_errno is set.
   13990                 :            :  */
   13991                 :            : static struct mlx5_aso_ct_pool *
   13992                 :          0 : flow_dv_ct_pool_create(struct rte_eth_dev *dev,
   13993                 :            :                        struct mlx5_aso_ct_action **ct_free)
   13994                 :            : {
   13995                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13996                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13997                 :            :         struct mlx5_aso_ct_pool *pool = NULL;
   13998                 :            :         struct mlx5_devx_obj *obj = NULL;
   13999                 :            :         uint32_t i;
   14000                 :            :         uint32_t log_obj_size = rte_log2_u32(MLX5_ASO_CT_ACTIONS_PER_POOL);
   14001                 :            :         size_t mem_size;
   14002                 :            : 
   14003                 :          0 :         obj = mlx5_devx_cmd_create_conn_track_offload_obj(priv->sh->cdev->ctx,
   14004                 :          0 :                                                           priv->sh->cdev->pdn,
   14005                 :            :                                                           log_obj_size);
   14006         [ #  # ]:          0 :         if (!obj) {
   14007                 :          0 :                 rte_errno = ENODATA;
   14008                 :          0 :                 DRV_LOG(ERR, "Failed to create conn_track_offload_obj using DevX.");
   14009                 :          0 :                 return NULL;
   14010                 :            :         }
   14011                 :            :         mem_size = sizeof(struct mlx5_aso_ct_action) *
   14012                 :            :                    MLX5_ASO_CT_ACTIONS_PER_POOL +
   14013                 :            :                    sizeof(*pool);
   14014                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   14015         [ #  # ]:          0 :         if (!pool) {
   14016                 :          0 :                 rte_errno = ENOMEM;
   14017                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   14018                 :          0 :                 return NULL;
   14019                 :            :         }
   14020                 :          0 :         pool->devx_obj = obj;
   14021                 :          0 :         pool->index = mng->next;
   14022                 :            :         /* Resize pools array if there is no room for the new pool in it. */
   14023   [ #  #  #  # ]:          0 :         if (pool->index == mng->n && flow_dv_aso_ct_pools_resize(dev)) {
   14024                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   14025                 :          0 :                 mlx5_free(pool);
   14026                 :          0 :                 return NULL;
   14027                 :            :         }
   14028                 :          0 :         mng->pools[pool->index] = pool;
   14029                 :          0 :         mng->next++;
   14030                 :            :         /* Assign the first action in the new pool, the rest go to free list. */
   14031                 :          0 :         *ct_free = &pool->actions[0];
   14032                 :            :         /* Lock outside, the list operation is safe here. */
   14033         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_CT_ACTIONS_PER_POOL; i++) {
   14034                 :            :                 /* refcnt is 0 when allocating the memory. */
   14035                 :          0 :                 pool->actions[i].offset = i;
   14036         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free_cts, &pool->actions[i], next);
   14037                 :            :         }
   14038                 :            :         return pool;
   14039                 :            : }
   14040                 :            : 
   14041                 :            : /*
   14042                 :            :  * Allocate a ASO CT action from free list.
   14043                 :            :  *
   14044                 :            :  * @param[in] dev
   14045                 :            :  *   Pointer to the Ethernet device structure.
   14046                 :            :  * @param[out] error
   14047                 :            :  *   Pointer to the error structure.
   14048                 :            :  *
   14049                 :            :  * @return
   14050                 :            :  *   Index to ASO CT action on success, 0 otherwise and rte_errno is set.
   14051                 :            :  */
   14052                 :            : static uint32_t
   14053                 :          0 : flow_dv_aso_ct_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error)
   14054                 :            : {
   14055                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14056                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   14057                 :          0 :         struct mlx5_aso_ct_action *ct = NULL;
   14058                 :            :         struct mlx5_aso_ct_pool *pool;
   14059                 :            :         uint8_t reg_c;
   14060                 :            :         uint32_t ct_idx;
   14061                 :            : 
   14062                 :            :         MLX5_ASSERT(mng);
   14063         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
   14064                 :          0 :                 rte_errno = ENOTSUP;
   14065                 :          0 :                 return 0;
   14066                 :            :         }
   14067                 :            :         /* Get a free CT action, if no, a new pool will be created. */
   14068                 :          0 :         rte_spinlock_lock(&mng->ct_sl);
   14069                 :          0 :         ct = LIST_FIRST(&mng->free_cts);
   14070         [ #  # ]:          0 :         if (ct) {
   14071         [ #  # ]:          0 :                 LIST_REMOVE(ct, next);
   14072         [ #  # ]:          0 :         } else if (!flow_dv_ct_pool_create(dev, &ct)) {
   14073                 :            :                 rte_spinlock_unlock(&mng->ct_sl);
   14074                 :          0 :                 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
   14075                 :            :                                    NULL, "failed to create ASO CT pool");
   14076                 :          0 :                 return 0;
   14077                 :            :         }
   14078                 :            :         rte_spinlock_unlock(&mng->ct_sl);
   14079                 :          0 :         pool = container_of(ct, struct mlx5_aso_ct_pool, actions[ct->offset]);
   14080                 :          0 :         ct_idx = MLX5_MAKE_CT_IDX(pool->index, ct->offset);
   14081                 :            :         /* 0: inactive, 1: created, 2+: used by flows. */
   14082                 :          0 :         rte_atomic_store_explicit(&ct->refcnt, 1, rte_memory_order_relaxed);
   14083                 :          0 :         reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, error);
   14084         [ #  # ]:          0 :         if (!ct->dr_action_orig) {
   14085                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   14086                 :          0 :                 ct->dr_action_orig = mlx5_glue->dv_create_flow_action_aso
   14087                 :          0 :                         (priv->sh->rx_domain, pool->devx_obj->obj,
   14088                 :            :                          ct->offset,
   14089                 :            :                          MLX5DV_DR_ACTION_FLAGS_ASO_CT_DIRECTION_INITIATOR,
   14090                 :          0 :                          reg_c - REG_C_0);
   14091                 :            : #else
   14092                 :            :                 RTE_SET_USED(reg_c);
   14093                 :            : #endif
   14094         [ #  # ]:          0 :                 if (!ct->dr_action_orig) {
   14095                 :          0 :                         flow_dv_aso_ct_dev_release(dev, ct_idx);
   14096                 :          0 :                         rte_flow_error_set(error, rte_errno,
   14097                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14098                 :            :                                            "failed to create ASO CT action");
   14099                 :          0 :                         return 0;
   14100                 :            :                 }
   14101                 :            :         }
   14102         [ #  # ]:          0 :         if (!ct->dr_action_rply) {
   14103                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   14104                 :          0 :                 ct->dr_action_rply = mlx5_glue->dv_create_flow_action_aso
   14105                 :          0 :                         (priv->sh->rx_domain, pool->devx_obj->obj,
   14106                 :            :                          ct->offset,
   14107                 :            :                          MLX5DV_DR_ACTION_FLAGS_ASO_CT_DIRECTION_RESPONDER,
   14108                 :          0 :                          reg_c - REG_C_0);
   14109                 :            : #endif
   14110         [ #  # ]:          0 :                 if (!ct->dr_action_rply) {
   14111                 :          0 :                         flow_dv_aso_ct_dev_release(dev, ct_idx);
   14112                 :          0 :                         rte_flow_error_set(error, rte_errno,
   14113                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14114                 :            :                                            "failed to create ASO CT action");
   14115                 :          0 :                         return 0;
   14116                 :            :                 }
   14117                 :            :         }
   14118                 :            :         return ct_idx;
   14119                 :            : }
   14120                 :            : 
   14121                 :            : /*
   14122                 :            :  * Create a conntrack object with context and actions by using ASO mechanism.
   14123                 :            :  *
   14124                 :            :  * @param[in] dev
   14125                 :            :  *   Pointer to rte_eth_dev structure.
   14126                 :            :  * @param[in] pro
   14127                 :            :  *   Pointer to conntrack information profile.
   14128                 :            :  * @param[out] error
   14129                 :            :  *   Pointer to the error structure.
   14130                 :            :  *
   14131                 :            :  * @return
   14132                 :            :  *   Index to conntrack object on success, 0 otherwise.
   14133                 :            :  */
   14134                 :            : static uint32_t
   14135                 :          0 : flow_dv_translate_create_conntrack(struct rte_eth_dev *dev,
   14136                 :            :                                    const struct rte_flow_action_conntrack *pro,
   14137                 :            :                                    struct rte_flow_error *error)
   14138                 :            : {
   14139                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14140                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   14141                 :            :         struct mlx5_aso_ct_action *ct;
   14142                 :            :         uint32_t idx;
   14143                 :            : 
   14144         [ #  # ]:          0 :         if (!sh->ct_aso_en)
   14145                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   14146                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14147                 :            :                                           "Connection is not supported");
   14148         [ #  # ]:          0 :         if (dev->data->port_id >= MLX5_INDIRECT_ACT_CT_MAX_PORT) {
   14149                 :          0 :                 rte_flow_error_set(error, EINVAL,
   14150                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   14151                 :            :                                    "CT supports port indexes up to "
   14152                 :            :                                    RTE_STR(MLX5_ACTION_CTX_CT_MAX_PORT));
   14153                 :          0 :                 return 0;
   14154                 :            :         }
   14155                 :          0 :         idx = flow_dv_aso_ct_alloc(dev, error);
   14156         [ #  # ]:          0 :         if (!idx)
   14157                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   14158                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14159                 :            :                                           "Failed to allocate CT object");
   14160                 :          0 :         ct = flow_aso_ct_get_by_dev_idx(dev, idx);
   14161         [ #  # ]:          0 :         if (mlx5_aso_ct_update_by_wqe(sh, MLX5_HW_INV_QUEUE, ct, pro, NULL, true)) {
   14162                 :          0 :                 flow_dv_aso_ct_dev_release(dev, idx);
   14163                 :          0 :                 rte_flow_error_set(error, EBUSY,
   14164                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14165                 :            :                                    "Failed to update CT");
   14166                 :          0 :                 return 0;
   14167                 :            :         }
   14168                 :          0 :         ct->is_original = !!pro->is_original_dir;
   14169                 :          0 :         ct->peer = pro->peer_port;
   14170                 :          0 :         return idx;
   14171                 :            : }
   14172                 :            : 
   14173                 :            : /**
   14174                 :            :  * Fill the flow matcher with DV spec.
   14175                 :            :  *
   14176                 :            :  * @param[in] dev
   14177                 :            :  *   Pointer to rte_eth_dev structure.
   14178                 :            :  * @param[in] items
   14179                 :            :  *   Pointer to the list of items.
   14180                 :            :  * @param[in] wks
   14181                 :            :  *   Pointer to the matcher workspace.
   14182                 :            :  * @param[in] key
   14183                 :            :  *   Pointer to the flow matcher key.
   14184                 :            :  * @param[in] key_type
   14185                 :            :  *   Key type.
   14186                 :            :  * @param[out] error
   14187                 :            :  *   Pointer to the error structure.
   14188                 :            :  *
   14189                 :            :  * @return
   14190                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14191                 :            :  */
   14192                 :            : static int
   14193                 :          0 : flow_dv_translate_items(struct rte_eth_dev *dev,
   14194                 :            :                         const struct rte_flow_item *items,
   14195                 :            :                         struct mlx5_dv_matcher_workspace *wks,
   14196                 :            :                         void *key, uint32_t key_type,
   14197                 :            :                         struct rte_flow_error *error)
   14198                 :            : {
   14199                 :          0 :         struct mlx5_flow_rss_desc *rss_desc = wks->rss_desc;
   14200                 :          0 :         uint8_t next_protocol = wks->next_protocol;
   14201                 :          0 :         int tunnel = !!(wks->item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14202                 :          0 :         int item_type = items->type;
   14203                 :          0 :         uint64_t last_item = wks->last_item;
   14204                 :            :         enum mlx5_l3_tunnel_detection l3_tunnel_detection;
   14205                 :            :         uint64_t l3_tunnel_flag;
   14206                 :            :         int ret;
   14207                 :            : 
   14208   [ #  #  #  #  :          0 :         switch (item_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
   14209                 :          0 :         case RTE_FLOW_ITEM_TYPE_ESP:
   14210                 :          0 :                 flow_dv_translate_item_esp(key, items, tunnel, key_type);
   14211                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14212                 :            :                 last_item = MLX5_FLOW_ITEM_ESP;
   14213                 :          0 :                 break;
   14214                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_ID:
   14215                 :          0 :                 flow_dv_translate_item_port_id
   14216                 :            :                         (dev, key, items, wks->attr, key_type);
   14217                 :            :                 last_item = MLX5_FLOW_ITEM_PORT_ID;
   14218                 :          0 :                 break;
   14219                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
   14220                 :          0 :                 flow_dv_translate_item_port_representor
   14221                 :            :                         (dev, key, key_type);
   14222                 :            :                 last_item = MLX5_FLOW_ITEM_PORT_REPRESENTOR;
   14223                 :          0 :                 break;
   14224                 :          0 :         case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
   14225                 :          0 :                 flow_dv_translate_item_represented_port
   14226                 :            :                         (dev, key, items, wks->attr, key_type);
   14227                 :            :                 last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
   14228                 :          0 :                 break;
   14229                 :          0 :         case RTE_FLOW_ITEM_TYPE_ETH:
   14230                 :          0 :                 flow_dv_translate_item_eth(key, items, tunnel,
   14231                 :            :                                            wks->group, key_type);
   14232         [ #  # ]:          0 :                 wks->priority = wks->action_flags &
   14233                 :          0 :                                 MLX5_FLOW_ACTION_DEFAULT_MISS &&
   14234         [ #  # ]:          0 :                                 !wks->external ?
   14235                 :            :                                 MLX5_PRIORITY_MAP_L3 :
   14236                 :            :                                 MLX5_PRIORITY_MAP_L2;
   14237         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
   14238                 :            :                                      MLX5_FLOW_LAYER_OUTER_L2;
   14239                 :            :                 break;
   14240                 :          0 :         case RTE_FLOW_ITEM_TYPE_VLAN:
   14241                 :          0 :                 flow_dv_translate_item_vlan(key, items, tunnel, wks, key_type);
   14242                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L2;
   14243                 :            :                 last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
   14244         [ #  # ]:          0 :                                           MLX5_FLOW_LAYER_INNER_VLAN) :
   14245                 :            :                                          (MLX5_FLOW_LAYER_OUTER_L2 |
   14246                 :            :                                           MLX5_FLOW_LAYER_OUTER_VLAN);
   14247                 :            :                 break;
   14248                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:
   14249                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14250                 :            :                 l3_tunnel_detection =
   14251                 :            :                         mlx5_flow_tunnel_ip_check(items, next_protocol,
   14252                 :            :                                                   wks->item_flags,
   14253                 :            :                                                   &l3_tunnel_flag);
   14254                 :            :                 if (l3_tunnel_detection == l3_tunnel_inner) {
   14255                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14256                 :            :                         tunnel = 1;
   14257                 :            :                 }
   14258                 :          0 :                 flow_dv_translate_item_ipv4(key, items, tunnel,
   14259                 :            :                                             wks->group, key_type);
   14260                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L3;
   14261         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
   14262                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV4;
   14263         [ #  # ]:          0 :                 if (l3_tunnel_detection == l3_tunnel_outer)
   14264                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14265                 :            :                 break;
   14266                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:
   14267                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14268                 :            :                 l3_tunnel_detection =
   14269                 :            :                         mlx5_flow_tunnel_ip_check(items, next_protocol,
   14270                 :            :                                                   wks->item_flags,
   14271                 :            :                                                   &l3_tunnel_flag);
   14272                 :            :                 if (l3_tunnel_detection == l3_tunnel_inner) {
   14273                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14274                 :            :                         tunnel = 1;
   14275                 :            :                 }
   14276                 :          0 :                 flow_dv_translate_item_ipv6(key, items, tunnel,
   14277                 :            :                                             wks->group, key_type);
   14278                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L3;
   14279         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
   14280                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV6;
   14281         [ #  # ]:          0 :                 if (l3_tunnel_detection == l3_tunnel_outer)
   14282                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14283                 :            :                 break;
   14284                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
   14285                 :          0 :                 flow_dv_translate_item_ipv6_frag_ext
   14286                 :            :                                         (key, items, tunnel, key_type);
   14287         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT :
   14288                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT;
   14289                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14290                 :            :                 break;
   14291                 :          0 :         case RTE_FLOW_ITEM_TYPE_TCP:
   14292                 :          0 :                 flow_dv_translate_item_tcp(key, items, tunnel, key_type);
   14293                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14294         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
   14295                 :            :                                      MLX5_FLOW_LAYER_OUTER_L4_TCP;
   14296                 :            :                 break;
   14297                 :          0 :         case RTE_FLOW_ITEM_TYPE_UDP:
   14298                 :          0 :                 flow_dv_translate_item_udp(key, items, tunnel, wks, key_type);
   14299                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14300         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
   14301                 :            :                                      MLX5_FLOW_LAYER_OUTER_L4_UDP;
   14302                 :            :                 break;
   14303                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE:
   14304         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14305                 :          0 :                 wks->tunnel_item = items;
   14306                 :          0 :                 wks->gre_item = items;
   14307                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14308                 :          0 :                 break;
   14309                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_KEY:
   14310                 :          0 :                 flow_dv_translate_item_gre_key(key, items, key_type);
   14311                 :            :                 last_item = MLX5_FLOW_LAYER_GRE_KEY;
   14312                 :          0 :                 break;
   14313                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
   14314         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14315                 :          0 :                 wks->tunnel_item = items;
   14316                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14317                 :          0 :                 break;
   14318                 :          0 :         case RTE_FLOW_ITEM_TYPE_NVGRE:
   14319         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14320                 :          0 :                 wks->tunnel_item = items;
   14321                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14322                 :          0 :                 break;
   14323                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN:
   14324                 :          0 :                 flow_dv_translate_item_vxlan(dev, wks->attr, key,
   14325                 :            :                                              items, tunnel, wks, key_type);
   14326         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14327                 :            :                 last_item = MLX5_FLOW_LAYER_VXLAN;
   14328                 :          0 :                 break;
   14329                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
   14330         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14331                 :          0 :                 wks->tunnel_item = items;
   14332                 :            :                 last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
   14333                 :          0 :                 break;
   14334                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE:
   14335         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14336                 :          0 :                 wks->tunnel_item = items;
   14337                 :            :                 last_item = MLX5_FLOW_LAYER_GENEVE;
   14338                 :          0 :                 break;
   14339                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
   14340                 :          0 :                 ret = flow_dv_translate_item_geneve_opt
   14341                 :            :                                 (dev, key, items, key_type, error);
   14342         [ #  # ]:          0 :                 if (ret)
   14343                 :          0 :                         return rte_flow_error_set(error, -ret,
   14344                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14345                 :            :                                 "cannot create GENEVE TLV option");
   14346                 :          0 :                 wks->geneve_tlv_option = 1;
   14347                 :            :                 last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
   14348                 :          0 :                 break;
   14349                 :          0 :         case RTE_FLOW_ITEM_TYPE_MPLS:
   14350                 :          0 :                 flow_dv_translate_item_mpls(key, items, last_item,
   14351                 :            :                                             tunnel, key_type);
   14352         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14353                 :            :                 last_item = MLX5_FLOW_LAYER_MPLS;
   14354                 :          0 :                 break;
   14355                 :          0 :         case RTE_FLOW_ITEM_TYPE_MARK:
   14356                 :          0 :                 flow_dv_translate_item_mark(dev, key, items, key_type);
   14357                 :            :                 last_item = MLX5_FLOW_ITEM_MARK;
   14358                 :          0 :                 break;
   14359                 :          0 :         case RTE_FLOW_ITEM_TYPE_META:
   14360                 :          0 :                 flow_dv_translate_item_meta
   14361                 :            :                                 (dev, key, wks->attr, items, key_type);
   14362                 :            :                 last_item = MLX5_FLOW_ITEM_METADATA;
   14363                 :          0 :                 break;
   14364                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP:
   14365                 :          0 :                 flow_dv_translate_item_icmp(key, items, tunnel, key_type);
   14366                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14367                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP;
   14368                 :          0 :                 break;
   14369                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP6:
   14370                 :          0 :                 flow_dv_translate_item_icmp6(key, items, tunnel, key_type);
   14371                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14372                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP6;
   14373                 :          0 :                 break;
   14374                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
   14375                 :            :         case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
   14376                 :          0 :                 flow_dv_translate_item_icmp6_echo(key, items, tunnel, key_type);
   14377                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14378                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP6;
   14379                 :          0 :                 break;
   14380                 :          0 :         case RTE_FLOW_ITEM_TYPE_TAG:
   14381                 :          0 :                 flow_dv_translate_item_tag(dev, key, items, key_type);
   14382                 :            :                 last_item = MLX5_FLOW_ITEM_TAG;
   14383                 :          0 :                 break;
   14384                 :          0 :         case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
   14385                 :          0 :                 flow_dv_translate_mlx5_item_tag(dev, key, items, key_type);
   14386                 :            :                 last_item = MLX5_FLOW_ITEM_TAG;
   14387                 :          0 :                 break;
   14388                 :          0 :         case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
   14389                 :          0 :                 ret = flow_dv_translate_item_tx_queue(dev, key, items, key_type);
   14390         [ #  # ]:          0 :                 if (ret)
   14391                 :          0 :                         return rte_flow_error_set(error, -ret,
   14392                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14393                 :            :                                 "invalid tx_queue item");
   14394                 :            :                 last_item = MLX5_FLOW_ITEM_SQ;
   14395                 :            :                 break;
   14396                 :          0 :         case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   14397                 :          0 :                 flow_dv_translate_item_sq(key, items, key_type);
   14398                 :            :                 last_item = MLX5_FLOW_ITEM_SQ;
   14399                 :          0 :                 break;
   14400                 :          0 :         case RTE_FLOW_ITEM_TYPE_GTP:
   14401                 :          0 :                 flow_dv_translate_item_gtp(key, items, tunnel, key_type);
   14402         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14403                 :            :                 last_item = MLX5_FLOW_LAYER_GTP;
   14404                 :          0 :                 break;
   14405                 :          0 :         case RTE_FLOW_ITEM_TYPE_GTP_PSC:
   14406                 :          0 :                 ret = flow_dv_translate_item_gtp_psc(key, items, key_type);
   14407         [ #  # ]:          0 :                 if (ret)
   14408                 :          0 :                         return rte_flow_error_set(error, -ret,
   14409                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14410                 :            :                                 "cannot create GTP PSC item");
   14411                 :            :                 last_item = MLX5_FLOW_LAYER_GTP_PSC;
   14412                 :            :                 break;
   14413                 :          0 :         case RTE_FLOW_ITEM_TYPE_ECPRI:
   14414         [ #  # ]:          0 :                 if (!mlx5_flex_parser_ecpri_exist(dev)) {
   14415                 :            :                         /* Create it only the first time to be used. */
   14416                 :          0 :                         ret = mlx5_flex_parser_ecpri_alloc(dev);
   14417         [ #  # ]:          0 :                         if (ret)
   14418                 :          0 :                                 return rte_flow_error_set
   14419                 :            :                                         (error, -ret,
   14420                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM,
   14421                 :            :                                         NULL,
   14422                 :            :                                         "cannot create eCPRI parser");
   14423                 :            :                 }
   14424                 :          0 :                 flow_dv_translate_item_ecpri
   14425                 :            :                                 (dev, key, items, last_item, key_type);
   14426                 :            :                 /* No other protocol should follow eCPRI layer. */
   14427                 :            :                 last_item = MLX5_FLOW_LAYER_ECPRI;
   14428                 :          0 :                 break;
   14429                 :          0 :         case RTE_FLOW_ITEM_TYPE_METER_COLOR:
   14430                 :          0 :                 flow_dv_translate_item_meter_color(dev, key, items, key_type);
   14431                 :            :                 last_item = MLX5_FLOW_ITEM_METER_COLOR;
   14432                 :          0 :                 break;
   14433         [ #  # ]:          0 :         case RTE_FLOW_ITEM_TYPE_INTEGRITY:
   14434                 :            :                 last_item = flow_dv_translate_item_integrity(items,
   14435                 :            :                                                              wks, key_type);
   14436                 :          0 :                 break;
   14437                 :          0 :         case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
   14438                 :          0 :                 flow_dv_translate_item_aggr_affinity(key, items, key_type);
   14439                 :            :                 last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
   14440                 :          0 :                 break;
   14441                 :          0 :         case RTE_FLOW_ITEM_TYPE_IB_BTH:
   14442                 :          0 :                 flow_dv_translate_item_ib_bth(key, items, tunnel, key_type);
   14443                 :            :                 last_item = MLX5_FLOW_ITEM_IB_BTH;
   14444                 :          0 :                 break;
   14445                 :          0 :         case RTE_FLOW_ITEM_TYPE_NSH:
   14446                 :            :                 last_item = MLX5_FLOW_ITEM_NSH;
   14447                 :          0 :                 break;
   14448                 :            :         default:
   14449                 :            :                 break;
   14450                 :            :         }
   14451                 :          0 :         wks->item_flags |= last_item;
   14452                 :          0 :         wks->last_item = last_item;
   14453                 :          0 :         wks->next_protocol = next_protocol;
   14454                 :          0 :         return 0;
   14455                 :            : }
   14456                 :            : 
   14457                 :            : static int
   14458                 :          0 : flow_dv_translate_items_geneve_opt_nta(struct rte_eth_dev *dev,
   14459                 :            :                                    const struct rte_flow_item *items,
   14460                 :            :                                    struct mlx5_flow_attr *attr,
   14461                 :            :                                    struct rte_flow_error *error)
   14462                 :            : {
   14463                 :          0 :         rte_be32_t geneve_mask = 0xffffffff;
   14464                 :          0 :         struct rte_pmd_mlx5_geneve_tlv geneve_tlv = {
   14465                 :            :                 /* Take from item spec, if changed, destroy and add new parser. */
   14466                 :            :                 .option_class                   = 0,
   14467                 :            :                 /* Take from item spec, if changed, destroy and add new parser. */
   14468                 :            :                 .option_type                    = 0,
   14469                 :            :                 /* 1DW is supported. */
   14470                 :            :                 .option_len                     = 1,
   14471                 :            :                 .match_on_class_mode            = 1,
   14472                 :            :                 .offset                         = 0,
   14473                 :            :                 .sample_len                     = 1,
   14474                 :            :                 .match_data_mask                = &geneve_mask
   14475                 :            :         };
   14476                 :          0 :         const struct rte_flow_item_geneve_opt *geneve_opt_v = items->spec;
   14477                 :          0 :         const struct rte_flow_item_geneve_opt *geneve_opt_m = items->mask;
   14478                 :            :         void *geneve_parser;
   14479                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14480                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
   14481                 :            :         struct mlx5_geneve_tlv_option *option;
   14482                 :            : #endif
   14483                 :            : 
   14484                 :            :         /* option length is not as supported. */
   14485         [ #  # ]:          0 :         if ((geneve_opt_v->option_len & geneve_opt_m->option_len) > geneve_tlv.option_len)
   14486                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   14487                 :            :                         RTE_FLOW_ERROR_TYPE_ITEM, items,
   14488                 :            :                         " GENEVE OPT length is not supported ");
   14489                 :          0 :         geneve_tlv.option_class = geneve_opt_v->option_class & geneve_opt_m->option_class;
   14490                 :          0 :         geneve_tlv.option_type = geneve_opt_v->option_type & geneve_opt_m->option_type;
   14491                 :            :         /* if parser doesn't exist */
   14492         [ #  # ]:          0 :         if (!priv->tlv_options) {
   14493                 :            :                 /* Create a GENEVE option parser. */
   14494                 :          0 :                 geneve_parser = mlx5_geneve_tlv_parser_create(attr->port_id,
   14495                 :            :                                                 &geneve_tlv, 1);
   14496         [ #  # ]:          0 :                 if (!geneve_parser)
   14497                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   14498                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, items,
   14499                 :            :                                 " GENEVE OPT parser creation failed ");
   14500                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
   14501                 :            :         } else {
   14502                 :            :                 /* Check if option exist in current parser. */
   14503                 :            :                 option = mlx5_geneve_tlv_option_get(priv,
   14504                 :            :                                                 geneve_tlv.option_type,
   14505                 :            :                                                 geneve_tlv.option_class);
   14506                 :            :                 if (!option)
   14507                 :            :                         return rte_flow_error_set(error, EINVAL,
   14508                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, items,
   14509                 :            :                                 " GENEVE OPT configured does not match this rule class/type");
   14510                 :            : #endif
   14511                 :            :         }
   14512                 :            :         return 0;
   14513                 :            : }
   14514                 :            : 
   14515                 :            : /**
   14516                 :            :  * Fill the flow matcher with DV spec for items supported in non template mode.
   14517                 :            :  *
   14518                 :            :  * @param[in] dev
   14519                 :            :  *   Pointer to rte_eth_dev structure.
   14520                 :            :  * @param[in] items
   14521                 :            :  *   Pointer to the list of items.
   14522                 :            :  * @param[in] wks
   14523                 :            :  *   Pointer to the matcher workspace.
   14524                 :            :  * @param[in] key
   14525                 :            :  *   Pointer to the flow matcher key.
   14526                 :            :  * @param[in] key_type
   14527                 :            :  *   Key type.
   14528                 :            :  * @param[out] error
   14529                 :            :  *   Pointer to the error structure.
   14530                 :            :  *
   14531                 :            :  * @return
   14532                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14533                 :            :  */
   14534                 :            : static int
   14535                 :          0 : flow_dv_translate_items_nta(struct rte_eth_dev *dev,
   14536                 :            :                         const struct rte_flow_item *items,
   14537                 :            :                         struct mlx5_dv_matcher_workspace *wks,
   14538                 :            :                         void *key, uint32_t key_type,
   14539                 :            :                         struct mlx5_flow_attr *attr,
   14540                 :            :                         struct rte_flow_error *error)
   14541                 :            : {
   14542                 :            :         int item_type;
   14543                 :            :         int ret = 0;
   14544                 :            :         int tunnel;
   14545                 :            :         /* Dummy structure to enable the key calculation for flex item. */
   14546                 :            :         struct mlx5_flow_dv_match_params flex_item_key;
   14547                 :            : 
   14548                 :          0 :         tunnel = !!(wks->item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14549                 :          0 :         item_type = items->type;
   14550   [ #  #  #  # ]:          0 :         switch (item_type) {
   14551                 :          0 :         case RTE_FLOW_ITEM_TYPE_CONNTRACK:
   14552                 :          0 :                 flow_dv_translate_item_aso_ct(dev, key, NULL, items);
   14553                 :          0 :                 wks->last_item = MLX5_FLOW_LAYER_ASO_CT;
   14554                 :          0 :                 break;
   14555                 :            :         /* TODO: remove once flex item translation is added to flow_dv_translate_items. */
   14556                 :          0 :         case RTE_FLOW_ITEM_TYPE_FLEX:
   14557                 :          0 :                 mlx5_flex_flow_translate_item(dev, key, flex_item_key.buf, items, tunnel != 0);
   14558         [ #  # ]:          0 :                 wks->last_item = tunnel ? MLX5_FLOW_ITEM_INNER_FLEX : MLX5_FLOW_ITEM_OUTER_FLEX;
   14559                 :          0 :                 break;
   14560                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
   14561                 :          0 :                 ret = flow_dv_translate_items_geneve_opt_nta(dev, items, attr, error);
   14562         [ #  # ]:          0 :                 if (ret)
   14563                 :            :                         return ret;
   14564                 :          0 :                 wks->last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
   14565                 :          0 :                 break;
   14566                 :          0 :         default:
   14567                 :          0 :                 ret = flow_dv_translate_items(dev, items, wks, key, key_type,  error);
   14568         [ #  # ]:          0 :                 if (ret)
   14569                 :            :                         return ret;
   14570                 :            :                 break;
   14571                 :            :         }
   14572                 :          0 :         wks->item_flags |= wks->last_item;
   14573                 :          0 :         return 0;
   14574                 :            : }
   14575                 :            : 
   14576                 :            : /**
   14577                 :            :  * Fill the HW steering flow with DV spec.
   14578                 :            :  *
   14579                 :            :  * @param[in] items
   14580                 :            :  *   Pointer to the list of items.
   14581                 :            :  * @param[in] attr
   14582                 :            :  *   Pointer to the flow attributes.
   14583                 :            :  * @param[in] key
   14584                 :            :  *   Pointer to the flow matcher key.
   14585                 :            :  * @param[in] key_type
   14586                 :            :  *   Key type.
   14587                 :            :  * @param[in, out] item_flags
   14588                 :            :  *   Pointer to the flow item flags.
   14589                 :            :  * @param[in, out] nt_flow
   14590                 :            :  *   Non template flow.
   14591                 :            :  * @param[out] error
   14592                 :            :  *   Pointer to the error structure.
   14593                 :            :  *
   14594                 :            :  * @return
   14595                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14596                 :            :  */
   14597                 :            : int
   14598                 :          0 : __flow_dv_translate_items_hws(const struct rte_flow_item *items,
   14599                 :            :                             struct mlx5_flow_attr *attr, void *key,
   14600                 :            :                             uint32_t key_type, uint64_t *item_flags,
   14601                 :            :                             uint8_t *match_criteria,
   14602                 :            :                             bool nt_flow,
   14603                 :            :                             struct rte_flow_error *error)
   14604                 :            : {
   14605                 :          0 :         struct mlx5_flow_workspace *flow_wks = mlx5_flow_push_thread_workspace();
   14606                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { .level = attr->rss_level };
   14607                 :          0 :         struct rte_flow_attr rattr = {
   14608                 :          0 :                 .group = attr->group,
   14609                 :          0 :                 .priority = attr->priority,
   14610                 :          0 :                 .ingress = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_NIC_RX),
   14611                 :          0 :                 .egress = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_NIC_TX),
   14612                 :          0 :                 .transfer = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_FDB),
   14613                 :            :         };
   14614                 :          0 :         struct mlx5_dv_matcher_workspace wks = {
   14615                 :          0 :                 .action_flags = attr->act_flags,
   14616         [ #  # ]:          0 :                 .item_flags = item_flags ? *item_flags : 0,
   14617                 :            :                 .external = 0,
   14618                 :            :                 .next_protocol = 0xff,
   14619                 :            :                 .attr = &rattr,
   14620                 :            :                 .rss_desc = &rss_desc,
   14621                 :            :                 .group = attr->group,
   14622                 :            :         };
   14623                 :            :         int ret = 0;
   14624                 :            : 
   14625                 :            :         RTE_SET_USED(flow_wks);
   14626         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
   14627                 :            :                 if (!mlx5_flow_os_item_supported(items->type)) {
   14628                 :            :                         ret = rte_flow_error_set(error, ENOTSUP,
   14629                 :            :                                                  RTE_FLOW_ERROR_TYPE_ITEM,
   14630                 :            :                                                  NULL, "item not supported");
   14631                 :            :                         goto exit;
   14632                 :            :                 }
   14633                 :            :                 /* Non template flow. */
   14634         [ #  # ]:          0 :                 if (nt_flow) {
   14635                 :          0 :                         ret = flow_dv_translate_items_nta(&rte_eth_devices[attr->port_id],
   14636                 :            :                                                           items, &wks, key, key_type, attr, error);
   14637         [ #  # ]:          0 :                         if (ret)
   14638                 :          0 :                                 goto exit;
   14639                 :            :                 } else {
   14640                 :          0 :                         ret = flow_dv_translate_items(&rte_eth_devices[attr->port_id],
   14641                 :            :                                                       items, &wks, key, key_type, error);
   14642         [ #  # ]:          0 :                         if (ret)
   14643                 :          0 :                                 goto exit;
   14644                 :            :                 }
   14645                 :            :         }
   14646         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
   14647                 :          0 :                 flow_dv_translate_item_integrity_post(key,
   14648                 :            :                                                       wks.integrity_items,
   14649                 :            :                                                       wks.item_flags,
   14650                 :            :                                                       key_type);
   14651                 :            :         }
   14652         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_LAYER_VXLAN_GPE) {
   14653                 :          0 :                 flow_dv_translate_item_vxlan_gpe(key,
   14654                 :            :                                                  wks.tunnel_item,
   14655                 :            :                                                  wks.item_flags,
   14656                 :            :                                                  key_type);
   14657         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GENEVE) {
   14658                 :          0 :                 flow_dv_translate_item_geneve(key,
   14659                 :            :                                               wks.tunnel_item,
   14660                 :            :                                               wks.item_flags,
   14661                 :            :                                               key_type);
   14662         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GRE) {
   14663         [ #  # ]:          0 :                 if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE) {
   14664                 :          0 :                         flow_dv_translate_item_gre(key,
   14665                 :            :                                                    wks.tunnel_item,
   14666                 :            :                                                    wks.item_flags,
   14667                 :            :                                                    key_type);
   14668         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION) {
   14669                 :          0 :                         flow_dv_translate_item_gre_option(key,
   14670                 :            :                                                           wks.tunnel_item,
   14671                 :            :                                                           wks.gre_item,
   14672                 :            :                                                           wks.item_flags,
   14673                 :            :                                                           key_type);
   14674         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
   14675                 :          0 :                         flow_dv_translate_item_nvgre(key,
   14676                 :            :                                                      wks.tunnel_item,
   14677                 :            :                                                      wks.item_flags,
   14678                 :            :                                                      key_type);
   14679                 :            :                 } else {
   14680                 :            :                         MLX5_ASSERT(false);
   14681                 :            :                 }
   14682                 :            :         }
   14683                 :            : 
   14684         [ #  # ]:          0 :         if (match_criteria)
   14685                 :          0 :                 *match_criteria = flow_dv_matcher_enable(key);
   14686         [ #  # ]:          0 :         if (item_flags)
   14687                 :          0 :                 *item_flags = wks.item_flags;
   14688                 :          0 : exit:
   14689                 :          0 :         mlx5_flow_pop_thread_workspace();
   14690                 :          0 :         return ret;
   14691                 :            : }
   14692                 :            : 
   14693                 :            : /**
   14694                 :            :  * Fill the HW steering flow with DV spec.
   14695                 :            :  * This function assumes given flow is created from template API.
   14696                 :            :  *
   14697                 :            :  * @param[in] items
   14698                 :            :  *   Pointer to the list of items.
   14699                 :            :  * @param[in] attr
   14700                 :            :  *   Pointer to the flow attributes.
   14701                 :            :  * @param[in] key
   14702                 :            :  *   Pointer to the flow matcher key.
   14703                 :            :  * @param[in] key_type
   14704                 :            :  *   Key type.
   14705                 :            :  * @param[in, out] item_flags
   14706                 :            :  *   Pointer to the flow item flags.
   14707                 :            :  * @param[out] error
   14708                 :            :  *   Pointer to the error structure.
   14709                 :            :  *
   14710                 :            :  * @return
   14711                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14712                 :            :  */
   14713                 :            : int
   14714                 :          0 : flow_dv_translate_items_hws(const struct rte_flow_item *items,
   14715                 :            :                             struct mlx5_flow_attr *attr, void *key,
   14716                 :            :                             uint32_t key_type, uint64_t *item_flags,
   14717                 :            :                             uint8_t *match_criteria,
   14718                 :            :                             struct rte_flow_error *error)
   14719                 :            : {
   14720                 :          0 :         return __flow_dv_translate_items_hws(items, attr, key, key_type, item_flags, match_criteria,
   14721                 :            :                                              false, error);
   14722                 :            : }
   14723                 :            : 
   14724                 :            : /**
   14725                 :            :  * Fill the SW steering flow with DV spec.
   14726                 :            :  *
   14727                 :            :  * @param[in] dev
   14728                 :            :  *   Pointer to rte_eth_dev structure.
   14729                 :            :  * @param[in, out] dev_flow
   14730                 :            :  *   Pointer to the sub flow.
   14731                 :            :  * @param[in] attr
   14732                 :            :  *   Pointer to the flow attributes.
   14733                 :            :  * @param[in] items
   14734                 :            :  *   Pointer to the list of items.
   14735                 :            :  * @param[in, out] matcher
   14736                 :            :  *   Pointer to the flow matcher.
   14737                 :            :  * @param[out] error
   14738                 :            :  *   Pointer to the error structure.
   14739                 :            :  *
   14740                 :            :  * @return
   14741                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14742                 :            :  */
   14743                 :            : static int
   14744                 :          0 : flow_dv_translate_items_sws(struct rte_eth_dev *dev,
   14745                 :            :                             struct mlx5_flow *dev_flow,
   14746                 :            :                             const struct rte_flow_attr *attr,
   14747                 :            :                             const struct rte_flow_item *items,
   14748                 :            :                             struct mlx5_flow_dv_matcher *matcher,
   14749                 :            :                             struct rte_flow_error *error)
   14750                 :            : {
   14751                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14752                 :          0 :         void *match_mask = matcher->mask.buf;
   14753                 :          0 :         void *match_value = dev_flow->dv.value.buf;
   14754                 :          0 :         struct mlx5_dv_matcher_workspace wks = {
   14755                 :          0 :                 .action_flags = dev_flow->act_flags,
   14756                 :            :                 .item_flags = 0,
   14757                 :          0 :                 .external = dev_flow->external,
   14758                 :            :                 .next_protocol = 0xff,
   14759                 :          0 :                 .group = dev_flow->dv.group,
   14760                 :            :                 .attr = attr,
   14761                 :          0 :                 .rss_desc = &((struct mlx5_flow_workspace *)
   14762                 :            :                              mlx5_flow_get_thread_workspace())->rss_desc,
   14763                 :            :         };
   14764                 :          0 :         struct mlx5_dv_matcher_workspace wks_m = wks;
   14765                 :            :         int item_type;
   14766                 :            :         int ret = 0;
   14767                 :            :         int tunnel;
   14768                 :            : 
   14769         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
   14770                 :          0 :                 if (!mlx5_flow_os_item_supported(items->type))
   14771                 :            :                         return rte_flow_error_set(error, ENOTSUP,
   14772                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
   14773                 :            :                                                   NULL, "item not supported");
   14774                 :          0 :                 tunnel = !!(wks.item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14775                 :            :                 item_type = items->type;
   14776   [ #  #  #  #  :          0 :                 switch (item_type) {
                      # ]
   14777                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
   14778                 :          0 :                         flow_dv_translate_item_aso_ct(dev, match_mask,
   14779                 :            :                                                       match_value, items);
   14780                 :          0 :                         wks.last_item = MLX5_FLOW_LAYER_ASO_CT;
   14781                 :          0 :                         break;
   14782                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
   14783                 :          0 :                         flow_dv_translate_item_flex(dev, match_mask,
   14784                 :            :                                                     match_value, items,
   14785                 :            :                                                     dev_flow, tunnel != 0);
   14786         [ #  # ]:          0 :                         wks.last_item = tunnel ? MLX5_FLOW_ITEM_INNER_FLEX :
   14787                 :            :                                                  MLX5_FLOW_ITEM_OUTER_FLEX;
   14788                 :          0 :                         break;
   14789                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
   14790                 :          0 :                         ret = flow_dv_translate_item_tx_queue(dev, match_value, items,
   14791                 :            :                                                               MLX5_SET_MATCHER_SW_V);
   14792         [ #  # ]:          0 :                         if (ret)
   14793                 :          0 :                                 return rte_flow_error_set(error, -ret,
   14794                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14795                 :            :                                         "invalid tx_queue item spec");
   14796                 :          0 :                         ret = flow_dv_translate_item_tx_queue(dev, match_mask, items,
   14797                 :            :                                                               MLX5_SET_MATCHER_SW_M);
   14798         [ #  # ]:          0 :                         if (ret)
   14799                 :          0 :                                 return rte_flow_error_set(error, -ret,
   14800                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14801                 :            :                                         "invalid tx_queue item mask");
   14802                 :            :                         break;
   14803                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   14804                 :          0 :                         flow_dv_translate_item_sq(match_value, items,
   14805                 :            :                                                   MLX5_SET_MATCHER_SW_V);
   14806                 :          0 :                         flow_dv_translate_item_sq(match_mask, items,
   14807                 :            :                                                   MLX5_SET_MATCHER_SW_M);
   14808                 :          0 :                         break;
   14809                 :          0 :                 default:
   14810                 :          0 :                         ret = flow_dv_translate_items(dev, items, &wks_m,
   14811                 :            :                                 match_mask, MLX5_SET_MATCHER_SW_M, error);
   14812         [ #  # ]:          0 :                         if (ret)
   14813                 :          0 :                                 return ret;
   14814                 :          0 :                         ret = flow_dv_translate_items(dev, items, &wks,
   14815                 :            :                                 match_value, MLX5_SET_MATCHER_SW_V, error);
   14816         [ #  # ]:          0 :                         if (ret)
   14817                 :          0 :                                 return ret;
   14818                 :            :                         break;
   14819                 :            :                 }
   14820                 :          0 :                 wks.item_flags |= wks.last_item;
   14821                 :            :         }
   14822                 :            :         /*
   14823                 :            :          * When E-Switch mode is enabled, we have two cases where we need to
   14824                 :            :          * set the source port manually.
   14825                 :            :          * The first one, is in case of NIC ingress steering rule, and the
   14826                 :            :          * second is E-Switch rule where no port_id item was found.
   14827                 :            :          * In both cases the source port is set according the current port
   14828                 :            :          * in use.
   14829                 :            :          */
   14830                 :          0 :         if (!(wks.item_flags & MLX5_FLOW_ITEM_PORT_ID) &&
   14831         [ #  # ]:          0 :             !(wks.item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT) &&
   14832                 :          0 :             !(wks.item_flags & MLX5_FLOW_ITEM_PORT_REPRESENTOR) &&
   14833         [ #  # ]:          0 :             priv->sh->esw_mode &&
   14834         [ #  # ]:          0 :             !attr->egress &&
   14835         [ #  # ]:          0 :             attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP) {
   14836         [ #  # ]:          0 :                 if (flow_dv_translate_item_port_id_all(dev, match_mask,
   14837                 :            :                                                    match_value, NULL, attr))
   14838                 :          0 :                         return -rte_errno;
   14839                 :            :         }
   14840         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
   14841                 :          0 :                 flow_dv_translate_item_integrity_post(match_mask,
   14842                 :            :                                                       wks_m.integrity_items,
   14843                 :            :                                                       wks_m.item_flags,
   14844                 :            :                                                       MLX5_SET_MATCHER_SW_M);
   14845                 :          0 :                 flow_dv_translate_item_integrity_post(match_value,
   14846                 :            :                                                       wks.integrity_items,
   14847                 :            :                                                       wks.item_flags,
   14848                 :            :                                                       MLX5_SET_MATCHER_SW_V);
   14849                 :            :         }
   14850         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_LAYER_VXLAN_GPE) {
   14851                 :          0 :                 flow_dv_translate_item_vxlan_gpe(match_mask,
   14852                 :            :                                                  wks.tunnel_item,
   14853                 :            :                                                  wks.item_flags,
   14854                 :            :                                                  MLX5_SET_MATCHER_SW_M);
   14855                 :          0 :                 flow_dv_translate_item_vxlan_gpe(match_value,
   14856                 :            :                                                  wks.tunnel_item,
   14857                 :            :                                                  wks.item_flags,
   14858                 :            :                                                  MLX5_SET_MATCHER_SW_V);
   14859         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GENEVE) {
   14860                 :          0 :                 flow_dv_translate_item_geneve(match_mask,
   14861                 :            :                                               wks.tunnel_item,
   14862                 :            :                                               wks.item_flags,
   14863                 :            :                                               MLX5_SET_MATCHER_SW_M);
   14864                 :          0 :                 flow_dv_translate_item_geneve(match_value,
   14865                 :            :                                               wks.tunnel_item,
   14866                 :            :                                               wks.item_flags,
   14867                 :            :                                               MLX5_SET_MATCHER_SW_V);
   14868         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GRE) {
   14869         [ #  # ]:          0 :                 if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE) {
   14870                 :          0 :                         flow_dv_translate_item_gre(match_mask,
   14871                 :            :                                                    wks.tunnel_item,
   14872                 :            :                                                    wks.item_flags,
   14873                 :            :                                                    MLX5_SET_MATCHER_SW_M);
   14874                 :          0 :                         flow_dv_translate_item_gre(match_value,
   14875                 :            :                                                    wks.tunnel_item,
   14876                 :            :                                                    wks.item_flags,
   14877                 :            :                                                    MLX5_SET_MATCHER_SW_V);
   14878         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
   14879                 :          0 :                         flow_dv_translate_item_nvgre(match_mask,
   14880                 :            :                                                      wks.tunnel_item,
   14881                 :            :                                                      wks.item_flags,
   14882                 :            :                                                      MLX5_SET_MATCHER_SW_M);
   14883                 :          0 :                         flow_dv_translate_item_nvgre(match_value,
   14884                 :            :                                                      wks.tunnel_item,
   14885                 :            :                                                      wks.item_flags,
   14886                 :            :                                                      MLX5_SET_MATCHER_SW_V);
   14887         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION) {
   14888                 :          0 :                         flow_dv_translate_item_gre_option(match_mask,
   14889                 :            :                                                           wks.tunnel_item,
   14890                 :            :                                                           wks.gre_item,
   14891                 :            :                                                           wks.item_flags,
   14892                 :            :                                                           MLX5_SET_MATCHER_SW_M);
   14893                 :          0 :                         flow_dv_translate_item_gre_option(match_value,
   14894                 :            :                                                           wks.tunnel_item,
   14895                 :            :                                                           wks.gre_item,
   14896                 :            :                                                           wks.item_flags,
   14897                 :            :                                                           MLX5_SET_MATCHER_SW_V);
   14898                 :            :                 } else {
   14899                 :            :                         MLX5_ASSERT(false);
   14900                 :            :                 }
   14901                 :            :         }
   14902                 :          0 :         dev_flow->handle->vf_vlan.tag = wks.vlan_tag;
   14903                 :          0 :         matcher->priority = wks.priority;
   14904                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
   14905                 :            :         MLX5_ASSERT(!flow_dv_check_valid_spec(match_mask, match_value));
   14906                 :            : #endif
   14907                 :            :         /*
   14908                 :            :          * Layers may be already initialized from prefix flow if this dev_flow
   14909                 :            :          * is the suffix flow.
   14910                 :            :          */
   14911                 :          0 :         dev_flow->handle->layers |= wks.item_flags;
   14912                 :            :         /*
   14913                 :            :          * Update geneve_tlv_option flag only it is set in workspace.
   14914                 :            :          * Avoid be overwritten by other sub mlx5_flows.
   14915                 :            :          */
   14916         [ #  # ]:          0 :         if (wks.geneve_tlv_option)
   14917                 :          0 :                 dev_flow->flow->geneve_tlv_option += wks.geneve_tlv_option;
   14918                 :            :         return 0;
   14919                 :            : }
   14920                 :            : 
   14921                 :            : /**
   14922                 :            :  * Fill the flow with DV spec, lock free
   14923                 :            :  * (mutex should be acquired by caller).
   14924                 :            :  *
   14925                 :            :  * @param[in] dev
   14926                 :            :  *   Pointer to rte_eth_dev structure.
   14927                 :            :  * @param[in, out] dev_flow
   14928                 :            :  *   Pointer to the sub flow.
   14929                 :            :  * @param[in] attr
   14930                 :            :  *   Pointer to the flow attributes.
   14931                 :            :  * @param[in] items
   14932                 :            :  *   Pointer to the list of items.
   14933                 :            :  * @param[in] actions
   14934                 :            :  *   Pointer to the list of actions.
   14935                 :            :  * @param[out] error
   14936                 :            :  *   Pointer to the error structure.
   14937                 :            :  *
   14938                 :            :  * @return
   14939                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14940                 :            :  */
   14941                 :            : static int
   14942                 :          0 : flow_dv_translate(struct rte_eth_dev *dev,
   14943                 :            :                   struct mlx5_flow *dev_flow,
   14944                 :            :                   const struct rte_flow_attr *attr,
   14945                 :            :                   const struct rte_flow_item items[],
   14946                 :            :                   const struct rte_flow_action actions[],
   14947                 :            :                   struct rte_flow_error *error)
   14948                 :            : {
   14949                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14950                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
   14951                 :          0 :         struct rte_flow *flow = dev_flow->flow;
   14952                 :          0 :         struct mlx5_flow_handle *handle = dev_flow->handle;
   14953                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   14954                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   14955                 :            :         uint64_t action_flags = 0;
   14956                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   14957                 :            :                 .mask = {
   14958                 :            :                         .size = sizeof(matcher.mask.buf),
   14959                 :            :                 },
   14960                 :            :         };
   14961                 :            :         int actions_n = 0;
   14962                 :            :         bool actions_end = false;
   14963                 :            :         union {
   14964                 :            :                 struct mlx5_flow_dv_modify_hdr_resource res;
   14965                 :            :                 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   14966                 :            :                             sizeof(struct mlx5_modification_cmd) *
   14967                 :            :                             (MLX5_MAX_MODIFY_NUM + 1)];
   14968                 :            :         } mhdr_dummy;
   14969                 :            :         struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
   14970                 :            :         const struct rte_flow_action_count *count = NULL;
   14971                 :            :         const struct rte_flow_action_age *non_shared_age = NULL;
   14972                 :          0 :         union flow_dv_attr flow_attr = { .attr = 0 };
   14973                 :            :         uint32_t tag_be;
   14974                 :            :         union mlx5_flow_tbl_key tbl_key;
   14975                 :            :         uint32_t modify_action_position = UINT32_MAX;
   14976                 :          0 :         struct rte_vlan_hdr vlan = { 0 };
   14977                 :            :         struct mlx5_flow_dv_dest_array_resource mdest_res;
   14978                 :            :         struct mlx5_flow_dv_sample_resource sample_res;
   14979                 :          0 :         void *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
   14980                 :            :         const struct rte_flow_action_sample *sample = NULL;
   14981                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   14982                 :            :         uint32_t sample_act_pos = UINT32_MAX;
   14983                 :            :         uint32_t age_act_pos = UINT32_MAX;
   14984                 :            :         uint32_t ipv6_tc_off = 0;
   14985                 :          0 :         uint32_t num_of_dest = 0;
   14986                 :            :         int tmp_actions_n = 0;
   14987                 :            :         uint32_t table;
   14988                 :            :         int ret = 0;
   14989                 :            :         const struct mlx5_flow_tunnel *tunnel = NULL;
   14990                 :          0 :         struct flow_grp_info grp_info = {
   14991                 :          0 :                 .external = !!dev_flow->external,
   14992                 :          0 :                 .transfer = !!attr->transfer,
   14993                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
   14994                 :          0 :                 .skip_scale = dev_flow->skip_scale &
   14995                 :            :                         (1 << MLX5_SCALE_FLOW_GROUP_BIT),
   14996                 :            :                 .std_tbl_fix = true,
   14997                 :            :         };
   14998                 :            : 
   14999         [ #  # ]:          0 :         if (!wks)
   15000                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   15001                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15002                 :            :                                           NULL,
   15003                 :            :                                           "failed to push flow workspace");
   15004         [ #  # ]:          0 :         rss_desc = &wks->rss_desc;
   15005                 :            :         memset(&mdest_res, 0, sizeof(struct mlx5_flow_dv_dest_array_resource));
   15006                 :            :         memset(&sample_res, 0, sizeof(struct mlx5_flow_dv_sample_resource));
   15007         [ #  # ]:          0 :         mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   15008                 :            :                                            MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   15009                 :            :         /* update normal path action resource into last index of array */
   15010                 :            :         sample_act = &mdest_res.sample_act[MLX5_MAX_DEST_NUM - 1];
   15011         [ #  # ]:          0 :         if (is_tunnel_offload_active(dev)) {
   15012         [ #  # ]:          0 :                 if (dev_flow->tunnel) {
   15013         [ #  # ]:          0 :                         RTE_VERIFY(dev_flow->tof_type ==
   15014                 :            :                                    MLX5_TUNNEL_OFFLOAD_MISS_RULE);
   15015                 :            :                         tunnel = dev_flow->tunnel;
   15016                 :            :                 } else {
   15017                 :          0 :                         tunnel = mlx5_get_tof(items, actions,
   15018                 :            :                                               &dev_flow->tof_type);
   15019                 :          0 :                         dev_flow->tunnel = tunnel;
   15020                 :            :                 }
   15021         [ #  # ]:          0 :                 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
   15022                 :            :                                         (dev, attr, tunnel, dev_flow->tof_type);
   15023                 :            :         }
   15024                 :          0 :         mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   15025                 :            :                                            MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   15026                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, attr->group, &table,
   15027                 :            :                                        &grp_info, error);
   15028         [ #  # ]:          0 :         if (ret)
   15029                 :            :                 return ret;
   15030                 :          0 :         dev_flow->dv.group = table;
   15031         [ #  # ]:          0 :         if (attr->transfer)
   15032                 :          0 :                 mhdr_res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
   15033                 :            :         /* number of actions must be set to 0 in case of dirty stack. */
   15034                 :          0 :         mhdr_res->actions_num = 0;
   15035         [ #  # ]:          0 :         if (is_flow_tunnel_match_rule(dev_flow->tof_type)) {
   15036                 :            :                 /*
   15037                 :            :                  * do not add decap action if match rule drops packet
   15038                 :            :                  * HW rejects rules with decap & drop
   15039                 :            :                  *
   15040                 :            :                  * if tunnel match rule was inserted before matching tunnel set
   15041                 :            :                  * rule flow table used in the match rule must be registered.
   15042                 :            :                  * current implementation handles that in the
   15043                 :            :                  * flow_dv_match_register() at the function end.
   15044                 :            :                  */
   15045                 :            :                 bool add_decap = true;
   15046                 :            :                 const struct rte_flow_action *ptr = actions;
   15047                 :            : 
   15048         [ #  # ]:          0 :                 for (; ptr->type != RTE_FLOW_ACTION_TYPE_END; ptr++) {
   15049         [ #  # ]:          0 :                         if (ptr->type == RTE_FLOW_ACTION_TYPE_DROP) {
   15050                 :            :                                 add_decap = false;
   15051                 :            :                                 break;
   15052                 :            :                         }
   15053                 :            :                 }
   15054         [ #  # ]:          0 :                 if (add_decap) {
   15055         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_decap(dev, dev_flow,
   15056                 :          0 :                                                            attr->transfer,
   15057                 :            :                                                            error))
   15058                 :          0 :                                 return -rte_errno;
   15059                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15060                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15061                 :            :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   15062                 :            :                 }
   15063                 :            :         }
   15064         [ #  # ]:          0 :         for (; !actions_end ; actions++) {
   15065                 :            :                 const struct rte_flow_action_queue *queue;
   15066                 :            :                 const struct rte_flow_action_rss *rss;
   15067                 :            :                 const struct rte_flow_action *action = actions;
   15068                 :            :                 const uint8_t *rss_key;
   15069                 :            :                 struct mlx5_flow_tbl_resource *tbl;
   15070                 :            :                 struct mlx5_aso_age_action *age_act;
   15071                 :            :                 struct mlx5_flow_counter *cnt_act;
   15072                 :          0 :                 uint32_t port_id = 0;
   15073                 :            :                 struct mlx5_flow_dv_port_id_action_resource port_id_resource;
   15074                 :          0 :                 int action_type = actions->type;
   15075                 :            :                 const struct rte_flow_action *found_action = NULL;
   15076                 :            :                 uint32_t jump_group = 0;
   15077                 :            :                 uint32_t owner_idx;
   15078                 :            :                 struct mlx5_aso_ct_action *ct;
   15079                 :            : 
   15080                 :            :                 if (!mlx5_flow_os_action_supported(action_type))
   15081                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   15082                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   15083                 :            :                                                   actions,
   15084                 :            :                                                   "action not supported");
   15085   [ #  #  #  #  :          0 :                 switch (action_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
   15086                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET:
   15087                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;
   15088                 :          0 :                         break;
   15089                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   15090                 :            :                         break;
   15091                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
   15092                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   15093         [ #  # ]:          0 :                         if (flow_dv_translate_action_port_id(dev, action,
   15094                 :            :                                                              &port_id, error))
   15095                 :          0 :                                 return -rte_errno;
   15096                 :          0 :                         port_id_resource.port_id = port_id;
   15097                 :            :                         MLX5_ASSERT(!handle->rix_port_id_action);
   15098         [ #  # ]:          0 :                         if (flow_dv_port_id_action_resource_register
   15099                 :            :                             (dev, &port_id_resource, dev_flow, error))
   15100                 :          0 :                                 return -rte_errno;
   15101                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15102                 :          0 :                                         dev_flow->dv.port_id_action->action;
   15103                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   15104                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_PORT_ID;
   15105                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   15106                 :          0 :                         num_of_dest++;
   15107                 :          0 :                         break;
   15108                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
   15109                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_FLAG;
   15110                 :          0 :                         wks->mark = 1;
   15111         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
   15112                 :          0 :                                 struct rte_flow_action_mark mark = {
   15113                 :            :                                         .id = MLX5_FLOW_MARK_DEFAULT,
   15114                 :            :                                 };
   15115                 :            : 
   15116         [ #  # ]:          0 :                                 if (flow_dv_convert_action_mark(dev, &mark,
   15117                 :            :                                                                 mhdr_res,
   15118                 :            :                                                                 error))
   15119                 :          0 :                                         return -rte_errno;
   15120                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
   15121                 :          0 :                                 break;
   15122                 :            :                         }
   15123                 :            :                         tag_be = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT);
   15124                 :            :                         /*
   15125                 :            :                          * Only one FLAG or MARK is supported per device flow
   15126                 :            :                          * right now. So the pointer to the tag resource must be
   15127                 :            :                          * zero before the register process.
   15128                 :            :                          */
   15129                 :            :                         MLX5_ASSERT(!handle->dvh.rix_tag);
   15130         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   15131                 :            :                                                           dev_flow, error))
   15132                 :          0 :                                 return -rte_errno;
   15133                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   15134                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15135                 :          0 :                                         dev_flow->dv.tag_resource->action;
   15136                 :          0 :                         break;
   15137                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
   15138                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
   15139                 :          0 :                         wks->mark = 1;
   15140         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
   15141                 :          0 :                                 const struct rte_flow_action_mark *mark =
   15142                 :            :                                         (const struct rte_flow_action_mark *)
   15143                 :            :                                                 actions->conf;
   15144                 :            : 
   15145         [ #  # ]:          0 :                                 if (flow_dv_convert_action_mark(dev, mark,
   15146                 :            :                                                                 mhdr_res,
   15147                 :            :                                                                 error))
   15148                 :          0 :                                         return -rte_errno;
   15149                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
   15150                 :          0 :                                 break;
   15151                 :            :                         }
   15152                 :            :                         /* Fall-through */
   15153                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
   15154                 :            :                         /* Legacy (non-extensive) MARK action. */
   15155                 :            :                         tag_be = mlx5_flow_mark_set
   15156                 :            :                               (((const struct rte_flow_action_mark *)
   15157         [ #  # ]:          0 :                                (actions->conf))->id);
   15158                 :            :                         MLX5_ASSERT(!handle->dvh.rix_tag);
   15159         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   15160                 :            :                                                           dev_flow, error))
   15161                 :          0 :                                 return -rte_errno;
   15162                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   15163                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15164                 :          0 :                                         dev_flow->dv.tag_resource->action;
   15165                 :          0 :                         break;
   15166                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_META:
   15167         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_meta
   15168                 :            :                                 (dev, mhdr_res, attr,
   15169                 :            :                                  (const struct rte_flow_action_set_meta *)
   15170                 :          0 :                                   actions->conf, error))
   15171                 :          0 :                                 return -rte_errno;
   15172                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_META;
   15173                 :          0 :                         break;
   15174                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
   15175         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_tag
   15176                 :            :                                 (dev, mhdr_res,
   15177                 :            :                                  (const struct rte_flow_action_set_tag *)
   15178                 :          0 :                                   actions->conf, error))
   15179                 :          0 :                                 return -rte_errno;
   15180                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15181                 :          0 :                         break;
   15182                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
   15183                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
   15184                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP;
   15185                 :          0 :                         break;
   15186                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   15187                 :          0 :                         queue = actions->conf;
   15188                 :          0 :                         rss_desc->queue_num = 1;
   15189                 :          0 :                         rss_desc->queue[0] = queue->index;
   15190                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
   15191                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
   15192                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_QUEUE;
   15193                 :          0 :                         num_of_dest++;
   15194                 :          0 :                         break;
   15195                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   15196                 :          0 :                         rss = actions->conf;
   15197                 :          0 :                         rss_desc->symmetric_hash_function =
   15198                 :          0 :                                 MLX5_RSS_IS_SYMM(rss->func);
   15199                 :          0 :                         memcpy(rss_desc->queue, rss->queue,
   15200         [ #  # ]:          0 :                                rss->queue_num * sizeof(uint16_t));
   15201                 :          0 :                         rss_desc->queue_num = rss->queue_num;
   15202                 :            :                         /* NULL RSS key indicates default RSS key. */
   15203         [ #  # ]:          0 :                         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   15204         [ #  # ]:          0 :                         memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   15205                 :            :                         /*
   15206                 :            :                          * rss->level and rss.types should be set in advance
   15207                 :            :                          * when expanding items for RSS.
   15208                 :            :                          */
   15209                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
   15210                 :          0 :                         dev_flow->handle->fate_action = rss_desc->shared_rss ?
   15211         [ #  # ]:          0 :                                 MLX5_FLOW_FATE_SHARED_RSS :
   15212                 :            :                                 MLX5_FLOW_FATE_QUEUE;
   15213                 :          0 :                         break;
   15214                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
   15215                 :          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15216                 :          0 :                         age_act = flow_aso_age_get_by_idx(dev, owner_idx);
   15217         [ #  # ]:          0 :                         if (flow->age == 0) {
   15218                 :          0 :                                 flow->age = owner_idx;
   15219                 :          0 :                                 rte_atomic_fetch_add_explicit(&age_act->refcnt, 1,
   15220                 :            :                                                    rte_memory_order_relaxed);
   15221                 :            :                         }
   15222                 :          0 :                         age_act_pos = actions_n++;
   15223                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
   15224                 :          0 :                         break;
   15225                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
   15226                 :          0 :                         dev_flow->dv.actions[actions_n] =
   15227                 :          0 :                                 flow_dv_translate_action_send_to_kernel(dev, attr,
   15228                 :            :                                                         error);
   15229         [ #  # ]:          0 :                         if (!dev_flow->dv.actions[actions_n])
   15230                 :          0 :                                 return -rte_errno;
   15231                 :          0 :                         actions_n++;
   15232                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
   15233                 :          0 :                         dev_flow->handle->fate_action =
   15234                 :            :                                         MLX5_FLOW_FATE_SEND_TO_KERNEL;
   15235                 :          0 :                         break;
   15236                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   15237                 :          0 :                         non_shared_age = action->conf;
   15238                 :          0 :                         age_act_pos = actions_n++;
   15239                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
   15240                 :          0 :                         break;
   15241                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
   15242         [ #  # ]:          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15243                 :            :                         cnt_act = flow_dv_counter_get_by_idx(dev, owner_idx,
   15244                 :            :                                                              NULL);
   15245                 :            :                         MLX5_ASSERT(cnt_act != NULL);
   15246                 :            :                         /**
   15247                 :            :                          * When creating meter drop flow in drop table, the
   15248                 :            :                          * counter should not overwrite the rte flow counter.
   15249                 :            :                          */
   15250         [ #  # ]:          0 :                         if (attr->group == MLX5_FLOW_TABLE_LEVEL_METER &&
   15251         [ #  # ]:          0 :                             dev_flow->dv.table_id == MLX5_MTR_TABLE_ID_DROP) {
   15252                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15253                 :          0 :                                                         cnt_act->action;
   15254                 :            :                         } else {
   15255         [ #  # ]:          0 :                                 if (flow->counter == 0) {
   15256                 :          0 :                                         flow->counter = owner_idx;
   15257                 :          0 :                                         rte_atomic_fetch_add_explicit
   15258                 :            :                                                 (&cnt_act->shared_info.refcnt,
   15259                 :            :                                                  1, rte_memory_order_relaxed);
   15260                 :            :                                 }
   15261                 :            :                                 /* Save information first, will apply later. */
   15262                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_COUNT;
   15263                 :            :                         }
   15264                 :            :                         break;
   15265                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   15266         [ #  # ]:          0 :                         if (!priv->sh->cdev->config.devx) {
   15267                 :          0 :                                 return rte_flow_error_set
   15268                 :            :                                               (error, ENOTSUP,
   15269                 :            :                                                RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15270                 :            :                                                NULL,
   15271                 :            :                                                "count action not supported");
   15272                 :            :                         }
   15273                 :            :                         /* Save information first, will apply later. */
   15274                 :          0 :                         count = action->conf;
   15275                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
   15276                 :          0 :                         break;
   15277                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
   15278                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15279                 :          0 :                                                 priv->sh->pop_vlan_action;
   15280                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
   15281                 :          0 :                         break;
   15282                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
   15283         [ #  # ]:          0 :                         if (!(action_flags &
   15284                 :            :                               MLX5_FLOW_ACTION_OF_SET_VLAN_VID))
   15285                 :          0 :                                 flow_dev_get_vlan_info_from_items(items, &vlan);
   15286         [ #  # ]:          0 :                         vlan.eth_proto = rte_be_to_cpu_16
   15287                 :            :                              ((((const struct rte_flow_action_of_push_vlan *)
   15288                 :            :                                                    actions->conf)->ethertype));
   15289                 :          0 :                         found_action = mlx5_flow_find_action
   15290                 :            :                                         (actions + 1,
   15291                 :            :                                          RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID);
   15292         [ #  # ]:          0 :                         if (found_action)
   15293                 :          0 :                                 mlx5_update_vlan_vid_pcp(found_action, &vlan);
   15294                 :          0 :                         found_action = mlx5_flow_find_action
   15295                 :            :                                         (actions + 1,
   15296                 :            :                                          RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP);
   15297         [ #  # ]:          0 :                         if (found_action)
   15298                 :          0 :                                 mlx5_update_vlan_vid_pcp(found_action, &vlan);
   15299         [ #  # ]:          0 :                         if (flow_dv_create_action_push_vlan
   15300                 :            :                                             (dev, attr, &vlan, dev_flow, error))
   15301                 :          0 :                                 return -rte_errno;
   15302                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15303                 :          0 :                                         dev_flow->dv.push_vlan_res->action;
   15304                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
   15305                 :          0 :                         break;
   15306                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
   15307                 :            :                         /* of_vlan_push action handled this action */
   15308                 :            :                         MLX5_ASSERT(action_flags &
   15309                 :            :                                     MLX5_FLOW_ACTION_OF_PUSH_VLAN);
   15310                 :            :                         break;
   15311                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
   15312         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
   15313                 :            :                                 break;
   15314                 :          0 :                         flow_dev_get_vlan_info_from_items(items, &vlan);
   15315                 :          0 :                         mlx5_update_vlan_vid_pcp(actions, &vlan);
   15316                 :            :                         /* If no VLAN push - this is a modify header action */
   15317         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_vlan_vid
   15318                 :            :                                                 (mhdr_res, actions, error))
   15319                 :          0 :                                 return -rte_errno;
   15320                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
   15321                 :          0 :                         break;
   15322                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   15323                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   15324         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_encap(dev, actions,
   15325                 :            :                                                            dev_flow,
   15326                 :          0 :                                                            attr->transfer,
   15327                 :            :                                                            error))
   15328                 :          0 :                                 return -rte_errno;
   15329                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15330                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15331                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   15332         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
   15333                 :          0 :                                 sample_act->action_flags |=
   15334                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15335                 :            :                         break;
   15336                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
   15337                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
   15338         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_decap(dev, dev_flow,
   15339                 :          0 :                                                            attr->transfer,
   15340                 :            :                                                            error))
   15341                 :          0 :                                 return -rte_errno;
   15342                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15343                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15344                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   15345                 :          0 :                         break;
   15346                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   15347                 :            :                         /* Handle encap with preceding decap. */
   15348         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_DECAP) {
   15349         [ #  # ]:          0 :                                 if (flow_dv_create_action_raw_encap
   15350                 :            :                                         (dev, actions, dev_flow, attr, error))
   15351                 :          0 :                                         return -rte_errno;
   15352                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15353                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15354                 :            :                         } else {
   15355                 :            :                                 /* Handle encap without preceding decap. */
   15356         [ #  # ]:          0 :                                 if (flow_dv_create_action_l2_encap
   15357                 :          0 :                                     (dev, actions, dev_flow, attr->transfer,
   15358                 :            :                                      error))
   15359                 :          0 :                                         return -rte_errno;
   15360                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15361                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15362                 :            :                         }
   15363                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   15364         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
   15365                 :          0 :                                 sample_act->action_flags |=
   15366                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15367                 :            :                         break;
   15368                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
   15369         [ #  # ]:          0 :                         while ((++action)->type == RTE_FLOW_ACTION_TYPE_VOID)
   15370                 :            :                                 ;
   15371         [ #  # ]:          0 :                         if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
   15372         [ #  # ]:          0 :                                 if (flow_dv_create_action_l2_decap
   15373                 :          0 :                                     (dev, dev_flow, attr->transfer, error))
   15374                 :          0 :                                         return -rte_errno;
   15375                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15376                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15377                 :            :                         }
   15378                 :            :                         /* If decap is followed by encap, handle it at encap. */
   15379                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   15380                 :          0 :                         break;
   15381                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_JUMP:
   15382                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15383                 :          0 :                                 (void *)(uintptr_t)action->conf;
   15384                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
   15385                 :          0 :                         break;
   15386                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
   15387                 :          0 :                         jump_group = ((const struct rte_flow_action_jump *)
   15388                 :          0 :                                                         action->conf)->group;
   15389                 :          0 :                         grp_info.std_tbl_fix = 0;
   15390         [ #  # ]:          0 :                         if (dev_flow->skip_scale &
   15391                 :            :                                 (1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT))
   15392                 :          0 :                                 grp_info.skip_scale = 1;
   15393                 :            :                         else
   15394                 :          0 :                                 grp_info.skip_scale = 0;
   15395                 :          0 :                         ret = mlx5_flow_group_to_table(dev, tunnel,
   15396                 :            :                                                        jump_group,
   15397                 :            :                                                        &table,
   15398                 :            :                                                        &grp_info, error);
   15399         [ #  # ]:          0 :                         if (ret)
   15400                 :          0 :                                 return ret;
   15401                 :          0 :                         tbl = flow_dv_tbl_resource_get(dev, table, attr->egress,
   15402                 :          0 :                                                        attr->transfer,
   15403                 :          0 :                                                        !!dev_flow->external,
   15404                 :            :                                                        tunnel, jump_group, 0,
   15405                 :            :                                                        0, error);
   15406         [ #  # ]:          0 :                         if (!tbl)
   15407                 :          0 :                                 return rte_flow_error_set
   15408                 :          0 :                                                 (error, errno,
   15409                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
   15410                 :            :                                                  NULL,
   15411                 :            :                                                  "cannot create jump action.");
   15412                 :            :                         if (flow_dv_jump_tbl_resource_register
   15413                 :            :                             (dev, tbl, dev_flow, error)) {
   15414                 :            :                                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   15415                 :            :                                 return rte_flow_error_set
   15416                 :            :                                                 (error, errno,
   15417                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
   15418                 :            :                                                  NULL,
   15419                 :            :                                                  "cannot create jump action.");
   15420                 :            :                         }
   15421                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15422                 :          0 :                                         dev_flow->dv.jump->action;
   15423                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
   15424                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP;
   15425                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_JUMP;
   15426                 :          0 :                         num_of_dest++;
   15427                 :          0 :                         break;
   15428                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
   15429                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
   15430         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_mac
   15431                 :            :                                         (mhdr_res, actions, error))
   15432                 :          0 :                                 return -rte_errno;
   15433                 :          0 :                         action_flags |= actions->type ==
   15434                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
   15435         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_MAC_SRC :
   15436                 :            :                                         MLX5_FLOW_ACTION_SET_MAC_DST;
   15437                 :          0 :                         break;
   15438                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
   15439                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
   15440         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv4
   15441                 :            :                                         (mhdr_res, actions, error))
   15442                 :          0 :                                 return -rte_errno;
   15443                 :          0 :                         action_flags |= actions->type ==
   15444                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
   15445         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_IPV4_SRC :
   15446                 :            :                                         MLX5_FLOW_ACTION_SET_IPV4_DST;
   15447                 :          0 :                         break;
   15448                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
   15449                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
   15450         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv6
   15451                 :            :                                         (mhdr_res, actions, error))
   15452                 :          0 :                                 return -rte_errno;
   15453                 :          0 :                         action_flags |= actions->type ==
   15454                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
   15455         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_IPV6_SRC :
   15456                 :            :                                         MLX5_FLOW_ACTION_SET_IPV6_DST;
   15457                 :          0 :                         break;
   15458                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
   15459                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
   15460         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tp
   15461                 :            :                                         (mhdr_res, actions, items,
   15462                 :          0 :                                          &flow_attr, dev_flow, !!(action_flags &
   15463                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15464                 :          0 :                                 return -rte_errno;
   15465                 :          0 :                         action_flags |= actions->type ==
   15466                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
   15467         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_TP_SRC :
   15468                 :            :                                         MLX5_FLOW_ACTION_SET_TP_DST;
   15469                 :          0 :                         break;
   15470                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
   15471         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_dec_ttl
   15472                 :            :                                         (mhdr_res, items, &flow_attr, dev_flow,
   15473                 :          0 :                                          !!(action_flags &
   15474                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15475                 :          0 :                                 return -rte_errno;
   15476                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEC_TTL;
   15477                 :          0 :                         break;
   15478                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
   15479         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ttl
   15480                 :            :                                         (mhdr_res, actions, items, &flow_attr,
   15481                 :          0 :                                          dev_flow, !!(action_flags &
   15482                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15483                 :          0 :                                 return -rte_errno;
   15484                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TTL;
   15485                 :          0 :                         break;
   15486                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
   15487                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
   15488         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tcp_seq
   15489                 :            :                                         (mhdr_res, actions, error))
   15490                 :          0 :                                 return -rte_errno;
   15491                 :          0 :                         action_flags |= actions->type ==
   15492                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
   15493         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_INC_TCP_SEQ :
   15494                 :            :                                         MLX5_FLOW_ACTION_DEC_TCP_SEQ;
   15495                 :          0 :                         break;
   15496                 :            : 
   15497                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
   15498                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
   15499         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tcp_ack
   15500                 :            :                                         (mhdr_res, actions, error))
   15501                 :          0 :                                 return -rte_errno;
   15502                 :          0 :                         action_flags |= actions->type ==
   15503                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
   15504         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_INC_TCP_ACK :
   15505                 :            :                                         MLX5_FLOW_ACTION_DEC_TCP_ACK;
   15506                 :          0 :                         break;
   15507                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
   15508         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_reg
   15509                 :            :                                         (mhdr_res, actions, error))
   15510                 :          0 :                                 return -rte_errno;
   15511                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15512                 :          0 :                         break;
   15513                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
   15514         [ #  # ]:          0 :                         if (flow_dv_convert_action_copy_mreg
   15515                 :            :                                         (dev, mhdr_res, actions, error))
   15516                 :          0 :                                 return -rte_errno;
   15517                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15518                 :          0 :                         break;
   15519                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
   15520                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
   15521                 :          0 :                         dev_flow->handle->fate_action =
   15522                 :            :                                         MLX5_FLOW_FATE_DEFAULT_MISS;
   15523                 :          0 :                         break;
   15524                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
   15525         [ #  # ]:          0 :                         if (!wks->fm)
   15526                 :          0 :                                 return rte_flow_error_set(error, rte_errno,
   15527                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
   15528                 :            :                                         NULL, "Failed to get meter in flow.");
   15529                 :            :                         /* Set the meter action. */
   15530                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15531                 :          0 :                                 wks->fm->meter_action_g;
   15532                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
   15533                 :          0 :                         break;
   15534                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
   15535         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv4_dscp(mhdr_res,
   15536                 :            :                                                               actions, error))
   15537                 :          0 :                                 return -rte_errno;
   15538                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
   15539                 :          0 :                         break;
   15540                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
   15541         [ #  # ]:          0 :                         if (mlx5_dv_modify_ipv6_traffic_class_supported(priv))
   15542                 :            :                                 ipv6_tc_off = MLX5_IPV6_HDR_DSCP_SHIFT;
   15543                 :            :                         else
   15544                 :            :                                 ipv6_tc_off = 0;
   15545         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv6_dscp(mhdr_res,
   15546                 :            :                                                               actions, ipv6_tc_off, error))
   15547                 :          0 :                                 return -rte_errno;
   15548                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
   15549                 :          0 :                         break;
   15550                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
   15551                 :          0 :                         sample_act_pos = actions_n;
   15552                 :          0 :                         sample = (const struct rte_flow_action_sample *)
   15553                 :            :                                  action->conf;
   15554                 :          0 :                         actions_n++;
   15555                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SAMPLE;
   15556                 :            :                         /* put encap action into group if work with port id */
   15557         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_ENCAP) &&
   15558                 :            :                             (action_flags & MLX5_FLOW_ACTION_PORT_ID))
   15559                 :          0 :                                 sample_act->action_flags |=
   15560                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15561                 :            :                         break;
   15562                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   15563         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_field
   15564                 :            :                                         (dev, mhdr_res, actions, attr, error))
   15565                 :          0 :                                 return -rte_errno;
   15566                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   15567                 :          0 :                         break;
   15568                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   15569                 :          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15570                 :          0 :                         ct = flow_aso_ct_get_by_idx(dev, owner_idx);
   15571         [ #  # ]:          0 :                         if (!ct)
   15572                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   15573                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15574                 :            :                                                 NULL,
   15575                 :            :                                                 "Failed to get CT object.");
   15576         [ #  # ]:          0 :                         if (mlx5_aso_ct_available(priv->sh, MLX5_HW_INV_QUEUE, ct))
   15577                 :          0 :                                 return rte_flow_error_set(error, rte_errno,
   15578                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15579                 :            :                                                 NULL,
   15580                 :            :                                                 "CT is unavailable.");
   15581         [ #  # ]:          0 :                         if (ct->is_original)
   15582                 :          0 :                                 dev_flow->dv.actions[actions_n] =
   15583                 :          0 :                                                         ct->dr_action_orig;
   15584                 :            :                         else
   15585                 :          0 :                                 dev_flow->dv.actions[actions_n] =
   15586                 :          0 :                                                         ct->dr_action_rply;
   15587         [ #  # ]:          0 :                         if (flow->ct == 0) {
   15588                 :          0 :                                 flow->indirect_type =
   15589                 :            :                                                 MLX5_INDIRECT_ACTION_TYPE_CT;
   15590                 :          0 :                                 flow->ct = owner_idx;
   15591                 :          0 :                                 rte_atomic_fetch_add_explicit(&ct->refcnt, 1,
   15592                 :            :                                                    rte_memory_order_relaxed);
   15593                 :            :                         }
   15594                 :          0 :                         actions_n++;
   15595                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
   15596                 :          0 :                         break;
   15597                 :          0 :                 case RTE_FLOW_ACTION_TYPE_END:
   15598                 :            :                         actions_end = true;
   15599         [ #  # ]:          0 :                         if (mhdr_res->actions_num) {
   15600                 :            :                                 /* create modify action if needed. */
   15601         [ #  # ]:          0 :                                 if (flow_dv_modify_hdr_resource_register
   15602                 :            :                                         (dev, mhdr_res, dev_flow, error))
   15603                 :          0 :                                         return -rte_errno;
   15604                 :          0 :                                 dev_flow->dv.actions[modify_action_position] =
   15605                 :          0 :                                         handle->dvh.modify_hdr->action;
   15606                 :            :                         }
   15607                 :            :                         /*
   15608                 :            :                          * Handle AGE and COUNT action by single HW counter
   15609                 :            :                          * when they are not shared.
   15610                 :            :                          */
   15611         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_AGE) {
   15612   [ #  #  #  # ]:          0 :                                 if ((non_shared_age && count) ||
   15613         [ #  # ]:          0 :                                     !flow_hit_aso_supported(priv, !dev_flow->dv.group)) {
   15614                 :            :                                         /* Creates age by counters. */
   15615                 :          0 :                                         cnt_act = flow_dv_prepare_counter
   15616                 :            :                                                                 (dev, dev_flow,
   15617                 :            :                                                                  flow, count,
   15618                 :            :                                                                  non_shared_age,
   15619                 :            :                                                                  error);
   15620         [ #  # ]:          0 :                                         if (!cnt_act)
   15621                 :          0 :                                                 return -rte_errno;
   15622                 :          0 :                                         dev_flow->dv.actions[age_act_pos] =
   15623                 :          0 :                                                                 cnt_act->action;
   15624                 :          0 :                                         break;
   15625                 :            :                                 }
   15626   [ #  #  #  # ]:          0 :                                 if (!flow->age && non_shared_age) {
   15627                 :          0 :                                         flow->age = flow_dv_aso_age_alloc
   15628                 :            :                                                                 (dev, error);
   15629         [ #  # ]:          0 :                                         if (!flow->age)
   15630                 :          0 :                                                 return -rte_errno;
   15631                 :          0 :                                         flow_dv_aso_age_params_init
   15632                 :            :                                                     (dev, flow->age,
   15633                 :          0 :                                                      non_shared_age->context ?
   15634                 :            :                                                      non_shared_age->context :
   15635                 :          0 :                                                      (void *)(uintptr_t)
   15636                 :          0 :                                                      (dev_flow->flow_idx),
   15637         [ #  # ]:          0 :                                                      non_shared_age->timeout);
   15638                 :            :                                 }
   15639                 :          0 :                                 age_act = flow_aso_age_get_by_idx(dev,
   15640                 :            :                                                                   flow->age);
   15641                 :          0 :                                 dev_flow->dv.actions[age_act_pos] =
   15642                 :          0 :                                                              age_act->dr_action;
   15643                 :            :                         }
   15644         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_COUNT) {
   15645                 :            :                                 /*
   15646                 :            :                                  * Create one count action, to be used
   15647                 :            :                                  * by all sub-flows.
   15648                 :            :                                  */
   15649                 :          0 :                                 cnt_act = flow_dv_prepare_counter(dev, dev_flow,
   15650                 :            :                                                                   flow, count,
   15651                 :            :                                                                   NULL, error);
   15652         [ #  # ]:          0 :                                 if (!cnt_act)
   15653                 :          0 :                                         return -rte_errno;
   15654                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15655                 :          0 :                                                                 cnt_act->action;
   15656                 :            :                         }
   15657                 :            :                 default:
   15658                 :            :                         break;
   15659                 :            :                 }
   15660   [ #  #  #  # ]:          0 :                 if (mhdr_res->actions_num &&
   15661                 :            :                     modify_action_position == UINT32_MAX)
   15662                 :          0 :                         modify_action_position = actions_n++;
   15663                 :            :         }
   15664                 :          0 :         dev_flow->act_flags = action_flags;
   15665                 :          0 :         ret = flow_dv_translate_items_sws(dev, dev_flow, attr, items, &matcher,
   15666                 :            :                                       error);
   15667         [ #  # ]:          0 :         if (ret)
   15668                 :          0 :                 return -rte_errno;
   15669         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_RSS) {
   15670                 :          0 :                 dev_flow->symmetric_hash_function = rss_desc->symmetric_hash_function;
   15671                 :          0 :                 flow_dv_hashfields_set(dev_flow->handle->layers,
   15672                 :            :                                        rss_desc,
   15673                 :            :                                        &dev_flow->hash_fields);
   15674                 :            :         }
   15675                 :            :         /* If has RSS action in the sample action, the Sample/Mirror resource
   15676                 :            :          * should be registered after the hash filed be update.
   15677                 :            :          */
   15678         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
   15679                 :          0 :                 ret = flow_dv_translate_action_sample(dev,
   15680                 :            :                                                       sample,
   15681                 :            :                                                       dev_flow, attr,
   15682                 :            :                                                       &num_of_dest,
   15683                 :            :                                                       sample_actions,
   15684                 :            :                                                       &sample_res,
   15685                 :            :                                                       error);
   15686         [ #  # ]:          0 :                 if (ret < 0)
   15687                 :            :                         return ret;
   15688                 :          0 :                 ret = flow_dv_create_action_sample(dev,
   15689                 :            :                                                    dev_flow,
   15690                 :            :                                                    num_of_dest,
   15691                 :            :                                                    &sample_res,
   15692                 :            :                                                    &mdest_res,
   15693                 :            :                                                    sample_actions,
   15694                 :            :                                                    action_flags,
   15695                 :            :                                                    error);
   15696         [ #  # ]:          0 :                 if (ret < 0)
   15697                 :          0 :                         return rte_flow_error_set
   15698                 :            :                                                 (error, rte_errno,
   15699                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15700                 :            :                                                 NULL,
   15701                 :            :                                                 "cannot create sample action");
   15702         [ #  # ]:          0 :                 if (num_of_dest > 1) {
   15703                 :          0 :                         dev_flow->dv.actions[sample_act_pos] =
   15704                 :          0 :                         dev_flow->dv.dest_array_res->action;
   15705                 :            :                 } else {
   15706                 :          0 :                         dev_flow->dv.actions[sample_act_pos] =
   15707                 :          0 :                         dev_flow->dv.sample_res->verbs_action;
   15708                 :            :                 }
   15709                 :            :         }
   15710                 :            :         /*
   15711                 :            :          * For multiple destination (sample action with ratio=1), the encap
   15712                 :            :          * action and port id action will be combined into group action.
   15713                 :            :          * So need remove the original these actions in the flow and only
   15714                 :            :          * use the sample action instead of.
   15715                 :            :          */
   15716         [ #  # ]:          0 :         if (num_of_dest > 1 &&
   15717   [ #  #  #  # ]:          0 :             (sample_act->dr_port_id_action || sample_act->dr_jump_action)) {
   15718                 :            :                 int i;
   15719                 :          0 :                 void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
   15720                 :            : 
   15721         [ #  # ]:          0 :                 for (i = 0; i < actions_n; i++) {
   15722         [ #  # ]:          0 :                         if ((sample_act->dr_encap_action &&
   15723                 :            :                                 sample_act->dr_encap_action ==
   15724   [ #  #  #  # ]:          0 :                                 dev_flow->dv.actions[i]) ||
   15725                 :          0 :                                 (sample_act->dr_port_id_action &&
   15726                 :            :                                 sample_act->dr_port_id_action ==
   15727         [ #  # ]:          0 :                                 dev_flow->dv.actions[i]) ||
   15728         [ #  # ]:          0 :                                 (sample_act->dr_jump_action &&
   15729                 :            :                                 sample_act->dr_jump_action ==
   15730         [ #  # ]:          0 :                                 dev_flow->dv.actions[i]))
   15731                 :          0 :                                 continue;
   15732                 :          0 :                         temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];
   15733                 :            :                 }
   15734                 :          0 :                 memcpy((void *)dev_flow->dv.actions,
   15735                 :            :                                 (void *)temp_actions,
   15736                 :            :                                 tmp_actions_n * sizeof(void *));
   15737                 :            :                 actions_n = tmp_actions_n;
   15738                 :            :         }
   15739                 :          0 :         dev_flow->dv.actions_n = actions_n;
   15740         [ #  # ]:          0 :         if (wks->skip_matcher_reg)
   15741                 :            :                 return 0;
   15742                 :            :         /* Register matcher. */
   15743                 :          0 :         matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
   15744                 :            :                                     matcher.mask.size);
   15745                 :          0 :         matcher.priority = mlx5_get_matcher_priority(dev, attr,
   15746                 :          0 :                                                      matcher.priority,
   15747                 :          0 :                                                      dev_flow->external);
   15748                 :            :         /**
   15749                 :            :          * When creating meter drop flow in drop table, using original
   15750                 :            :          * 5-tuple match, the matcher priority should be lower than
   15751                 :            :          * mtr_id matcher.
   15752                 :            :          */
   15753         [ #  # ]:          0 :         if (attr->group == MLX5_FLOW_TABLE_LEVEL_METER &&
   15754   [ #  #  #  # ]:          0 :             dev_flow->dv.table_id == MLX5_MTR_TABLE_ID_DROP &&
   15755                 :            :             matcher.priority <= MLX5_REG_BITS)
   15756                 :          0 :                 matcher.priority += MLX5_REG_BITS;
   15757                 :            :         /* reserved field no needs to be set to 0 here. */
   15758                 :          0 :         tbl_key.is_fdb = attr->transfer;
   15759                 :          0 :         tbl_key.is_egress = attr->egress;
   15760                 :          0 :         tbl_key.level = dev_flow->dv.group;
   15761                 :          0 :         tbl_key.id = dev_flow->dv.table_id;
   15762         [ #  # ]:          0 :         if (flow_dv_matcher_register(dev, &matcher, &tbl_key, dev_flow,
   15763                 :            :                                      tunnel, attr->group, error))
   15764                 :          0 :                 return -rte_errno;
   15765                 :            :         return 0;
   15766                 :            : }
   15767                 :            : 
   15768                 :            : /**
   15769                 :            :  * Set hash RX queue by hash fields (see enum ibv_rx_hash_fields)
   15770                 :            :  * and tunnel.
   15771                 :            :  *
   15772                 :            :  * @param[in, out] action
   15773                 :            :  *   Shred RSS action holding hash RX queue objects.
   15774                 :            :  * @param[in] hash_fields
   15775                 :            :  *   Defines combination of packet fields to participate in RX hash.
   15776                 :            :  * @param[in] tunnel
   15777                 :            :  *   Tunnel type
   15778                 :            :  * @param[in] hrxq_idx
   15779                 :            :  *   Hash RX queue index to set.
   15780                 :            :  *
   15781                 :            :  * @return
   15782                 :            :  *   0 on success, otherwise negative errno value.
   15783                 :            :  */
   15784                 :            : static int
   15785                 :          0 : __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
   15786                 :            :                               const uint64_t hash_fields,
   15787                 :            :                               uint32_t hrxq_idx)
   15788                 :            : {
   15789                 :            :         uint32_t *hrxqs = action->hrxq;
   15790                 :            : 
   15791   [ #  #  #  #  :          0 :         switch (hash_fields & ~IBV_RX_HASH_INNER) {
          #  #  #  #  #  
                   #  # ]
   15792                 :          0 :         case MLX5_RSS_HASH_IPV4:
   15793                 :            :                 /* fall-through. */
   15794                 :            :         case MLX5_RSS_HASH_IPV4_DST_ONLY:
   15795                 :            :                 /* fall-through. */
   15796                 :            :         case MLX5_RSS_HASH_IPV4_SRC_ONLY:
   15797                 :          0 :                 hrxqs[0] = hrxq_idx;
   15798                 :          0 :                 return 0;
   15799                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   15800                 :            :                 /* fall-through. */
   15801                 :            :         case MLX5_RSS_HASH_IPV4_TCP_DST_ONLY:
   15802                 :            :                 /* fall-through. */
   15803                 :            :         case MLX5_RSS_HASH_IPV4_TCP_SRC_ONLY:
   15804                 :          0 :                 hrxqs[1] = hrxq_idx;
   15805                 :          0 :                 return 0;
   15806                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   15807                 :            :                 /* fall-through. */
   15808                 :            :         case MLX5_RSS_HASH_IPV4_UDP_DST_ONLY:
   15809                 :            :                 /* fall-through. */
   15810                 :            :         case MLX5_RSS_HASH_IPV4_UDP_SRC_ONLY:
   15811                 :          0 :                 hrxqs[2] = hrxq_idx;
   15812                 :          0 :                 return 0;
   15813                 :          0 :         case MLX5_RSS_HASH_IPV6:
   15814                 :            :                 /* fall-through. */
   15815                 :            :         case MLX5_RSS_HASH_IPV6_DST_ONLY:
   15816                 :            :                 /* fall-through. */
   15817                 :            :         case MLX5_RSS_HASH_IPV6_SRC_ONLY:
   15818                 :          0 :                 hrxqs[3] = hrxq_idx;
   15819                 :          0 :                 return 0;
   15820                 :          0 :         case MLX5_RSS_HASH_IPV6_TCP:
   15821                 :            :                 /* fall-through. */
   15822                 :            :         case MLX5_RSS_HASH_IPV6_TCP_DST_ONLY:
   15823                 :            :                 /* fall-through. */
   15824                 :            :         case MLX5_RSS_HASH_IPV6_TCP_SRC_ONLY:
   15825                 :          0 :                 hrxqs[4] = hrxq_idx;
   15826                 :          0 :                 return 0;
   15827                 :          0 :         case MLX5_RSS_HASH_IPV6_UDP:
   15828                 :            :                 /* fall-through. */
   15829                 :            :         case MLX5_RSS_HASH_IPV6_UDP_DST_ONLY:
   15830                 :            :                 /* fall-through. */
   15831                 :            :         case MLX5_RSS_HASH_IPV6_UDP_SRC_ONLY:
   15832                 :          0 :                 hrxqs[5] = hrxq_idx;
   15833                 :          0 :                 return 0;
   15834                 :          0 :         case MLX5_RSS_HASH_NONE:
   15835                 :          0 :                 hrxqs[6] = hrxq_idx;
   15836                 :          0 :                 return 0;
   15837                 :          0 :         case MLX5_RSS_HASH_IPV4_ESP:
   15838                 :          0 :                 hrxqs[7] = hrxq_idx;
   15839                 :          0 :                 return 0;
   15840                 :          0 :         case MLX5_RSS_HASH_IPV6_ESP:
   15841                 :          0 :                 hrxqs[8] = hrxq_idx;
   15842                 :          0 :                 return 0;
   15843                 :          0 :         case MLX5_RSS_HASH_ESP_SPI:
   15844                 :          0 :                 hrxqs[9] = hrxq_idx;
   15845                 :          0 :                 return 0;
   15846                 :            :         default:
   15847                 :            :                 return -1;
   15848                 :            :         }
   15849                 :            : }
   15850                 :            : 
   15851                 :            : /**
   15852                 :            :  * Look up for hash RX queue by hash fields (see enum ibv_rx_hash_fields)
   15853                 :            :  * and tunnel.
   15854                 :            :  *
   15855                 :            :  * @param[in] dev
   15856                 :            :  *   Pointer to the Ethernet device structure.
   15857                 :            :  * @param[in] idx
   15858                 :            :  *   Shared RSS action ID holding hash RX queue objects.
   15859                 :            :  * @param[in] hash_fields
   15860                 :            :  *   Defines combination of packet fields to participate in RX hash.
   15861                 :            :  * @param[in] tunnel
   15862                 :            :  *   Tunnel type
   15863                 :            :  *
   15864                 :            :  * @return
   15865                 :            :  *   Valid hash RX queue index, otherwise 0.
   15866                 :            :  */
   15867                 :            : uint32_t
   15868                 :          0 : flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
   15869                 :            :                                const uint64_t hash_fields)
   15870                 :            : {
   15871                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15872                 :            :         struct mlx5_shared_action_rss *shared_rss =
   15873                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   15874                 :            :         const uint32_t *hrxqs = shared_rss->hrxq;
   15875                 :            : 
   15876   [ #  #  #  #  :          0 :         switch (hash_fields & ~IBV_RX_HASH_INNER) {
          #  #  #  #  #  
                   #  # ]
   15877                 :          0 :         case MLX5_RSS_HASH_IPV4:
   15878                 :            :                 /* fall-through. */
   15879                 :            :         case MLX5_RSS_HASH_IPV4_DST_ONLY:
   15880                 :            :                 /* fall-through. */
   15881                 :            :         case MLX5_RSS_HASH_IPV4_SRC_ONLY:
   15882                 :          0 :                 return hrxqs[0];
   15883                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   15884                 :            :                 /* fall-through. */
   15885                 :            :         case MLX5_RSS_HASH_IPV4_TCP_DST_ONLY:
   15886                 :            :                 /* fall-through. */
   15887                 :            :         case MLX5_RSS_HASH_IPV4_TCP_SRC_ONLY:
   15888                 :          0 :                 return hrxqs[1];
   15889                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   15890                 :            :                 /* fall-through. */
   15891                 :            :         case MLX5_RSS_HASH_IPV4_UDP_DST_ONLY:
   15892                 :            :                 /* fall-through. */
   15893                 :            :         case MLX5_RSS_HASH_IPV4_UDP_SRC_ONLY:
   15894                 :          0 :                 return hrxqs[2];
   15895                 :          0 :         case MLX5_RSS_HASH_IPV6:
   15896                 :            :                 /* fall-through. */
   15897                 :            :         case MLX5_RSS_HASH_IPV6_DST_ONLY:
   15898                 :            :                 /* fall-through. */
   15899                 :            :         case MLX5_RSS_HASH_IPV6_SRC_ONLY:
   15900                 :          0 :                 return hrxqs[3];
   15901                 :          0 :         case MLX5_RSS_HASH_IPV6_TCP:
   15902                 :            :                 /* fall-through. */
   15903                 :            :         case MLX5_RSS_HASH_IPV6_TCP_DST_ONLY:
   15904                 :            :                 /* fall-through. */
   15905                 :            :         case MLX5_RSS_HASH_IPV6_TCP_SRC_ONLY:
   15906                 :          0 :                 return hrxqs[4];
   15907                 :          0 :         case MLX5_RSS_HASH_IPV6_UDP:
   15908                 :            :                 /* fall-through. */
   15909                 :            :         case MLX5_RSS_HASH_IPV6_UDP_DST_ONLY:
   15910                 :            :                 /* fall-through. */
   15911                 :            :         case MLX5_RSS_HASH_IPV6_UDP_SRC_ONLY:
   15912                 :          0 :                 return hrxqs[5];
   15913                 :          0 :         case MLX5_RSS_HASH_NONE:
   15914                 :          0 :                 return hrxqs[6];
   15915                 :          0 :         case MLX5_RSS_HASH_IPV4_ESP:
   15916                 :          0 :                 return hrxqs[7];
   15917                 :          0 :         case MLX5_RSS_HASH_IPV6_ESP:
   15918                 :          0 :                 return hrxqs[8];
   15919                 :          0 :         case MLX5_RSS_HASH_ESP_SPI:
   15920                 :          0 :                 return hrxqs[9];
   15921                 :            :         default:
   15922                 :            :                 return 0;
   15923                 :            :         }
   15924                 :            : 
   15925                 :            : }
   15926                 :            : 
   15927                 :            : /**
   15928                 :            :  * Apply the flow to the NIC, lock free,
   15929                 :            :  * (mutex should be acquired by caller).
   15930                 :            :  *
   15931                 :            :  * @param[in] dev
   15932                 :            :  *   Pointer to the Ethernet device structure.
   15933                 :            :  * @param[in, out] flow
   15934                 :            :  *   Pointer to flow structure.
   15935                 :            :  * @param[out] error
   15936                 :            :  *   Pointer to error structure.
   15937                 :            :  *
   15938                 :            :  * @return
   15939                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   15940                 :            :  */
   15941                 :            : static int
   15942                 :          0 : flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
   15943                 :            :               struct rte_flow_error *error)
   15944                 :            : {
   15945                 :            :         struct mlx5_flow_dv_workspace *dv;
   15946                 :            :         struct mlx5_flow_handle *dh;
   15947                 :            :         struct mlx5_flow_handle_dv *dv_h;
   15948                 :            :         struct mlx5_flow *dev_flow;
   15949                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15950                 :            :         uint32_t handle_idx;
   15951                 :            :         int n;
   15952                 :            :         int err;
   15953                 :            :         int idx;
   15954                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   15955                 :          0 :         struct mlx5_flow_rss_desc *rss_desc = &wks->rss_desc;
   15956                 :            :         uint8_t misc_mask;
   15957                 :            : 
   15958                 :            :         MLX5_ASSERT(wks);
   15959         [ #  # ]:          0 :         for (idx = wks->flow_idx - 1; idx >= 0; idx--) {
   15960                 :          0 :                 dev_flow = &wks->flows[idx];
   15961                 :            :                 dv = &dev_flow->dv;
   15962                 :          0 :                 dh = dev_flow->handle;
   15963                 :            :                 dv_h = &dh->dvh;
   15964                 :          0 :                 n = dv->actions_n;
   15965         [ #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_DROP) {
   15966         [ #  # ]:          0 :                         if (dv->transfer) {
   15967                 :            :                                 MLX5_ASSERT(priv->sh->dr_drop_action);
   15968                 :          0 :                                 dv->actions[n++] = priv->sh->dr_drop_action;
   15969                 :            :                         } else {
   15970                 :            : #ifdef HAVE_MLX5DV_DR
   15971                 :            :                                 /* DR supports drop action placeholder. */
   15972                 :            :                                 MLX5_ASSERT(priv->sh->dr_drop_action);
   15973                 :          0 :                                 dv->actions[n++] = dv->group ?
   15974         [ #  # ]:          0 :                                         priv->sh->dr_drop_action :
   15975                 :            :                                         priv->root_drop_action;
   15976                 :            : #else
   15977                 :            :                                 /* For DV we use the explicit drop queue. */
   15978                 :            :                                 MLX5_ASSERT(priv->drop_queue.hrxq);
   15979                 :            :                                 dv->actions[n++] =
   15980                 :            :                                                 priv->drop_queue.hrxq->action;
   15981                 :            : #endif
   15982                 :            :                         }
   15983         [ #  # ]:          0 :                 } else if ((dh->fate_action == MLX5_FLOW_FATE_QUEUE &&
   15984   [ #  #  #  # ]:          0 :                            !dv_h->rix_sample && !dv_h->rix_dest_array)) {
   15985                 :            :                         struct mlx5_hrxq *hrxq;
   15986                 :            :                         uint32_t hrxq_idx;
   15987                 :            : 
   15988                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow, rss_desc,
   15989                 :            :                                                     &hrxq_idx);
   15990         [ #  # ]:          0 :                         if (!hrxq) {
   15991                 :          0 :                                 rte_flow_error_set
   15992                 :            :                                         (error, rte_errno,
   15993                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   15994                 :            :                                          "cannot get hash queue");
   15995                 :          0 :                                 goto error;
   15996                 :            :                         }
   15997                 :          0 :                         dh->rix_hrxq = hrxq_idx;
   15998                 :          0 :                         dv->actions[n++] = hrxq->action;
   15999         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
   16000                 :            :                         struct mlx5_hrxq *hrxq = NULL;
   16001                 :            :                         uint32_t hrxq_idx;
   16002                 :            : 
   16003                 :          0 :                         hrxq_idx = flow_dv_action_rss_hrxq_lookup(dev,
   16004                 :            :                                                 rss_desc->shared_rss,
   16005                 :            :                                                 dev_flow->hash_fields);
   16006         [ #  # ]:          0 :                         if (hrxq_idx)
   16007                 :          0 :                                 hrxq = mlx5_ipool_get
   16008                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_HRXQ],
   16009                 :            :                                          hrxq_idx);
   16010         [ #  # ]:          0 :                         if (!hrxq) {
   16011                 :          0 :                                 rte_flow_error_set
   16012                 :            :                                         (error, rte_errno,
   16013                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16014                 :            :                                          "cannot get hash queue");
   16015                 :          0 :                                 goto error;
   16016                 :            :                         }
   16017                 :          0 :                         dh->rix_srss = rss_desc->shared_rss;
   16018                 :          0 :                         dv->actions[n++] = hrxq->action;
   16019         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_DEFAULT_MISS) {
   16020         [ #  # ]:          0 :                         if (!priv->sh->default_miss_action) {
   16021                 :          0 :                                 rte_flow_error_set
   16022                 :            :                                         (error, rte_errno,
   16023                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16024                 :            :                                          "default miss action not be created.");
   16025                 :          0 :                                 goto error;
   16026                 :            :                         }
   16027                 :          0 :                         dv->actions[n++] = priv->sh->default_miss_action;
   16028                 :            :                 }
   16029         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(dv_h->matcher->mask.buf);
   16030                 :            :                 __flow_dv_adjust_buf_size(&dv->value.size, misc_mask);
   16031                 :          0 :                 err = mlx5_flow_os_create_flow(dv_h->matcher->matcher_object,
   16032                 :          0 :                                                (void *)&dv->value, n,
   16033                 :          0 :                                                dv->actions, &dh->drv_flow);
   16034                 :            :                 if (err) {
   16035                 :          0 :                         rte_flow_error_set
   16036                 :          0 :                                 (error, errno,
   16037                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16038                 :            :                                 NULL,
   16039         [ #  # ]:          0 :                                 (!priv->sh->config.allow_duplicate_pattern &&
   16040         [ #  # ]:          0 :                                 errno == EEXIST) ?
   16041                 :            :                                 "duplicating pattern is not allowed" :
   16042                 :            :                                 "hardware refuses to create flow");
   16043                 :          0 :                         goto error;
   16044                 :            :                 }
   16045         [ #  # ]:          0 :                 if (priv->vmwa_context &&
   16046   [ #  #  #  # ]:          0 :                     dh->vf_vlan.tag && !dh->vf_vlan.created) {
   16047                 :            :                         /*
   16048                 :            :                          * The rule contains the VLAN pattern.
   16049                 :            :                          * For VF we are going to create VLAN
   16050                 :            :                          * interface to make hypervisor set correct
   16051                 :            :                          * e-Switch vport context.
   16052                 :            :                          */
   16053                 :          0 :                         mlx5_vlan_vmwa_acquire(dev, &dh->vf_vlan);
   16054                 :            :                 }
   16055                 :            :         }
   16056                 :            :         return 0;
   16057                 :          0 : error:
   16058                 :          0 :         err = rte_errno; /* Save rte_errno before cleanup. */
   16059   [ #  #  #  #  :          0 :         SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
                   #  # ]
   16060                 :            :                        handle_idx, dh, next) {
   16061                 :            :                 /* hrxq is union, don't clear it if the flag is not set. */
   16062   [ #  #  #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE && dh->rix_hrxq &&
   16063   [ #  #  #  # ]:          0 :                     !dh->dvh.rix_sample && !dh->dvh.rix_dest_array) {
   16064                 :          0 :                         mlx5_hrxq_release(dev, dh->rix_hrxq);
   16065                 :          0 :                         dh->rix_hrxq = 0;
   16066         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
   16067                 :          0 :                         dh->rix_srss = 0;
   16068                 :            :                 }
   16069   [ #  #  #  # ]:          0 :                 if (dh->vf_vlan.tag && dh->vf_vlan.created)
   16070                 :          0 :                         mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
   16071                 :            :         }
   16072                 :          0 :         rte_errno = err; /* Restore rte_errno. */
   16073                 :          0 :         return -rte_errno;
   16074                 :            : }
   16075                 :            : 
   16076                 :            : void
   16077                 :          0 : flow_matcher_remove_cb(void *tool_ctx __rte_unused,
   16078                 :            :                           struct mlx5_list_entry *entry)
   16079                 :            : {
   16080                 :            :         struct mlx5_flow_dv_matcher *resource = container_of(entry,
   16081                 :            :                                                              typeof(*resource),
   16082                 :            :                                                              entry);
   16083                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16084                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16085                 :            : 
   16086         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16087                 :          0 :                 claim_zero(mlx5dr_bwc_matcher_destroy((struct mlx5dr_bwc_matcher *)
   16088                 :            :                                                                 resource->matcher_object));
   16089                 :            :         else
   16090                 :            : #endif
   16091                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(resource->matcher_object));
   16092                 :          0 :         mlx5_free(resource);
   16093                 :          0 : }
   16094                 :            : 
   16095                 :            : /**
   16096                 :            :  * Release the flow matcher.
   16097                 :            :  *
   16098                 :            :  * @param dev
   16099                 :            :  *   Pointer to Ethernet device.
   16100                 :            :  * @param port_id
   16101                 :            :  *   Index to port ID action resource.
   16102                 :            :  *
   16103                 :            :  * @return
   16104                 :            :  *   1 while a reference on it exists, 0 when freed.
   16105                 :            :  */
   16106                 :            : static int
   16107                 :          0 : flow_dv_matcher_release(struct rte_eth_dev *dev,
   16108                 :            :                         struct mlx5_flow_handle *handle)
   16109                 :            : {
   16110                 :          0 :         struct mlx5_flow_dv_matcher *matcher = handle->dvh.matcher;
   16111                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(matcher->tbl,
   16112                 :            :                                                             typeof(*tbl), tbl);
   16113                 :            :         int ret;
   16114                 :            : 
   16115                 :            :         MLX5_ASSERT(matcher->matcher_object);
   16116                 :          0 :         ret = mlx5_list_unregister(tbl->matchers, &matcher->entry);
   16117                 :          0 :         flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl->tbl);
   16118                 :          0 :         return ret;
   16119                 :            : }
   16120                 :            : 
   16121                 :            : void
   16122                 :          0 : flow_encap_decap_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16123                 :            : {
   16124                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16125                 :            :         struct mlx5_flow_dv_encap_decap_resource *res =
   16126                 :            :                                        container_of(entry, typeof(*res), entry);
   16127                 :            : 
   16128                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16129         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16130                 :          0 :                 claim_zero(mlx5dr_action_destroy(res->action));
   16131                 :            :         else
   16132                 :            : #endif
   16133                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
   16134                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx);
   16135                 :          0 : }
   16136                 :            : 
   16137                 :            : /**
   16138                 :            :  * Release an encap/decap resource.
   16139                 :            :  *
   16140                 :            :  * @param dev
   16141                 :            :  *   Pointer to Ethernet device.
   16142                 :            :  * @param encap_decap_idx
   16143                 :            :  *   Index of encap decap resource.
   16144                 :            :  *
   16145                 :            :  * @return
   16146                 :            :  *   1 while a reference on it exists, 0 when freed.
   16147                 :            :  */
   16148                 :            : int
   16149                 :          0 : flow_encap_decap_resource_release(struct rte_eth_dev *dev,
   16150                 :            :                                      uint32_t encap_decap_idx)
   16151                 :            : {
   16152                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16153                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
   16154                 :            : 
   16155                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
   16156                 :            :                                   encap_decap_idx);
   16157         [ #  # ]:          0 :         if (!resource)
   16158                 :            :                 return 0;
   16159                 :            :         MLX5_ASSERT(resource->action);
   16160                 :          0 :         return mlx5_hlist_unregister(priv->sh->encaps_decaps, &resource->entry);
   16161                 :            : }
   16162                 :            : 
   16163                 :            : /**
   16164                 :            :  * Release an jump to table action resource.
   16165                 :            :  *
   16166                 :            :  * @param dev
   16167                 :            :  *   Pointer to Ethernet device.
   16168                 :            :  * @param rix_jump
   16169                 :            :  *   Index to the jump action resource.
   16170                 :            :  *
   16171                 :            :  * @return
   16172                 :            :  *   1 while a reference on it exists, 0 when freed.
   16173                 :            :  */
   16174                 :            : static int
   16175                 :          0 : flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
   16176                 :            :                                   uint32_t rix_jump)
   16177                 :            : {
   16178                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16179                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   16180                 :            : 
   16181                 :          0 :         tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP],
   16182                 :            :                                   rix_jump);
   16183         [ #  # ]:          0 :         if (!tbl_data)
   16184                 :            :                 return 0;
   16185                 :          0 :         return flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl_data->tbl);
   16186                 :            : }
   16187                 :            : 
   16188                 :            : void
   16189                 :          0 : flow_modify_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16190                 :            : {
   16191                 :            :         struct mlx5_flow_dv_modify_hdr_resource *res =
   16192                 :            :                 container_of(entry, typeof(*res), entry);
   16193                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16194                 :            : 
   16195                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16196         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16197                 :          0 :                 claim_zero(mlx5dr_action_destroy(res->action));
   16198                 :            :         else
   16199                 :            : #endif
   16200                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
   16201                 :          0 :         mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
   16202                 :          0 : }
   16203                 :            : 
   16204                 :            : /**
   16205                 :            :  * Release a modify-header resource.
   16206                 :            :  *
   16207                 :            :  * @param dev
   16208                 :            :  *   Pointer to Ethernet device.
   16209                 :            :  * @param handle
   16210                 :            :  *   Pointer to mlx5_flow_handle.
   16211                 :            :  *
   16212                 :            :  * @return
   16213                 :            :  *   1 while a reference on it exists, 0 when freed.
   16214                 :            :  */
   16215                 :            : static int
   16216                 :            : flow_dv_modify_hdr_resource_release(struct rte_eth_dev *dev,
   16217                 :            :                                     struct mlx5_flow_handle *handle)
   16218                 :            : {
   16219                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16220                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry = handle->dvh.modify_hdr;
   16221                 :            : 
   16222                 :            :         MLX5_ASSERT(entry->action);
   16223                 :          0 :         return mlx5_hlist_unregister(priv->sh->modify_cmds, &entry->entry);
   16224                 :            : }
   16225                 :            : 
   16226                 :            : void
   16227                 :          0 : flow_dv_port_id_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16228                 :            : {
   16229                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16230                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource =
   16231                 :            :                                   container_of(entry, typeof(*resource), entry);
   16232                 :            : 
   16233                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16234                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], resource->idx);
   16235                 :          0 : }
   16236                 :            : 
   16237                 :            : /**
   16238                 :            :  * Release port ID action resource.
   16239                 :            :  *
   16240                 :            :  * @param dev
   16241                 :            :  *   Pointer to Ethernet device.
   16242                 :            :  * @param handle
   16243                 :            :  *   Pointer to mlx5_flow_handle.
   16244                 :            :  *
   16245                 :            :  * @return
   16246                 :            :  *   1 while a reference on it exists, 0 when freed.
   16247                 :            :  */
   16248                 :            : static int
   16249                 :          0 : flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
   16250                 :            :                                         uint32_t port_id)
   16251                 :            : {
   16252                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16253                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
   16254                 :            : 
   16255                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID], port_id);
   16256         [ #  # ]:          0 :         if (!resource)
   16257                 :            :                 return 0;
   16258                 :            :         MLX5_ASSERT(resource->action);
   16259                 :          0 :         return mlx5_list_unregister(priv->sh->port_id_action_list,
   16260                 :            :                                     &resource->entry);
   16261                 :            : }
   16262                 :            : 
   16263                 :            : /**
   16264                 :            :  * Release shared RSS action resource.
   16265                 :            :  *
   16266                 :            :  * @param dev
   16267                 :            :  *   Pointer to Ethernet device.
   16268                 :            :  * @param srss
   16269                 :            :  *   Shared RSS action index.
   16270                 :            :  */
   16271                 :            : static void
   16272                 :          0 : flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss)
   16273                 :            : {
   16274                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16275                 :            :         struct mlx5_shared_action_rss *shared_rss;
   16276                 :            : 
   16277                 :          0 :         shared_rss = mlx5_ipool_get
   16278                 :          0 :                         (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], srss);
   16279                 :          0 :         rte_atomic_fetch_sub_explicit(&shared_rss->refcnt, 1, rte_memory_order_relaxed);
   16280                 :          0 : }
   16281                 :            : 
   16282                 :            : void
   16283                 :          0 : flow_dv_push_vlan_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16284                 :            : {
   16285                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16286                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource =
   16287                 :            :                         container_of(entry, typeof(*resource), entry);
   16288                 :            : 
   16289                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16290                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], resource->idx);
   16291                 :          0 : }
   16292                 :            : 
   16293                 :            : /**
   16294                 :            :  * Release push vlan action resource.
   16295                 :            :  *
   16296                 :            :  * @param dev
   16297                 :            :  *   Pointer to Ethernet device.
   16298                 :            :  * @param handle
   16299                 :            :  *   Pointer to mlx5_flow_handle.
   16300                 :            :  *
   16301                 :            :  * @return
   16302                 :            :  *   1 while a reference on it exists, 0 when freed.
   16303                 :            :  */
   16304                 :            : static int
   16305                 :          0 : flow_dv_push_vlan_action_resource_release(struct rte_eth_dev *dev,
   16306                 :            :                                           struct mlx5_flow_handle *handle)
   16307                 :            : {
   16308                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16309                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
   16310                 :          0 :         uint32_t idx = handle->dvh.rix_push_vlan;
   16311                 :            : 
   16312                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx);
   16313         [ #  # ]:          0 :         if (!resource)
   16314                 :            :                 return 0;
   16315                 :            :         MLX5_ASSERT(resource->action);
   16316                 :          0 :         return mlx5_list_unregister(priv->sh->push_vlan_action_list,
   16317                 :            :                                     &resource->entry);
   16318                 :            : }
   16319                 :            : 
   16320                 :            : /**
   16321                 :            :  * Release the fate resource.
   16322                 :            :  *
   16323                 :            :  * @param dev
   16324                 :            :  *   Pointer to Ethernet device.
   16325                 :            :  * @param handle
   16326                 :            :  *   Pointer to mlx5_flow_handle.
   16327                 :            :  */
   16328                 :            : static void
   16329                 :          0 : flow_dv_fate_resource_release(struct rte_eth_dev *dev,
   16330                 :            :                                struct mlx5_flow_handle *handle)
   16331                 :            : {
   16332         [ #  # ]:          0 :         if (!handle->rix_fate)
   16333                 :            :                 return;
   16334   [ #  #  #  #  :          0 :         switch (handle->fate_action) {
                      # ]
   16335                 :          0 :         case MLX5_FLOW_FATE_QUEUE:
   16336   [ #  #  #  # ]:          0 :                 if (!handle->dvh.rix_sample && !handle->dvh.rix_dest_array)
   16337                 :          0 :                         mlx5_hrxq_release(dev, handle->rix_hrxq);
   16338                 :            :                 break;
   16339                 :          0 :         case MLX5_FLOW_FATE_JUMP:
   16340                 :          0 :                 flow_dv_jump_tbl_resource_release(dev, handle->rix_jump);
   16341                 :          0 :                 break;
   16342                 :          0 :         case MLX5_FLOW_FATE_PORT_ID:
   16343                 :          0 :                 flow_dv_port_id_action_resource_release(dev,
   16344                 :            :                                 handle->rix_port_id_action);
   16345                 :          0 :                 break;
   16346                 :            :         case MLX5_FLOW_FATE_SEND_TO_KERNEL:
   16347                 :            :                 /* In case of send_to_kernel action the actual release of
   16348                 :            :                  * resource is done when all shared DR resources are released
   16349                 :            :                  * since this resource is created once and always reused.
   16350                 :            :                  */
   16351                 :            :                 break;
   16352                 :          0 :         default:
   16353                 :          0 :                 DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action);
   16354                 :          0 :                 break;
   16355                 :            :         }
   16356                 :          0 :         handle->rix_fate = 0;
   16357                 :            : }
   16358                 :            : 
   16359                 :            : void
   16360                 :          0 : flow_dv_sample_remove_cb(void *tool_ctx __rte_unused,
   16361                 :            :                          struct mlx5_list_entry *entry)
   16362                 :            : {
   16363                 :            :         struct mlx5_flow_dv_sample_resource *resource = container_of(entry,
   16364                 :            :                                                               typeof(*resource),
   16365                 :            :                                                               entry);
   16366                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   16367                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16368                 :            : 
   16369         [ #  # ]:          0 :         if (resource->verbs_action)
   16370                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action
   16371                 :            :                                                       (resource->verbs_action));
   16372         [ #  # ]:          0 :         if (resource->normal_path_tbl)
   16373                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   16374                 :            :                                              resource->normal_path_tbl);
   16375                 :          0 :         flow_dv_sample_sub_actions_release(dev, &resource->sample_idx);
   16376                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], resource->idx);
   16377                 :          0 :         DRV_LOG(DEBUG, "sample resource %p: removed", (void *)resource);
   16378                 :          0 : }
   16379                 :            : 
   16380                 :            : /**
   16381                 :            :  * Release an sample resource.
   16382                 :            :  *
   16383                 :            :  * @param dev
   16384                 :            :  *   Pointer to Ethernet device.
   16385                 :            :  * @param handle
   16386                 :            :  *   Pointer to mlx5_flow_handle.
   16387                 :            :  *
   16388                 :            :  * @return
   16389                 :            :  *   1 while a reference on it exists, 0 when freed.
   16390                 :            :  */
   16391                 :            : static int
   16392                 :          0 : flow_dv_sample_resource_release(struct rte_eth_dev *dev,
   16393                 :            :                                      struct mlx5_flow_handle *handle)
   16394                 :            : {
   16395                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16396                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   16397                 :            : 
   16398                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_SAMPLE],
   16399                 :            :                                   handle->dvh.rix_sample);
   16400         [ #  # ]:          0 :         if (!resource)
   16401                 :            :                 return 0;
   16402                 :            :         MLX5_ASSERT(resource->verbs_action);
   16403                 :          0 :         return mlx5_list_unregister(priv->sh->sample_action_list,
   16404                 :            :                                     &resource->entry);
   16405                 :            : }
   16406                 :            : 
   16407                 :            : void
   16408                 :          0 : flow_dv_dest_array_remove_cb(void *tool_ctx __rte_unused,
   16409                 :            :                              struct mlx5_list_entry *entry)
   16410                 :            : {
   16411                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   16412                 :            :                         container_of(entry, typeof(*resource), entry);
   16413                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   16414                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16415                 :            :         uint32_t i = 0;
   16416                 :            : 
   16417                 :            :         MLX5_ASSERT(resource->action);
   16418         [ #  # ]:          0 :         if (resource->action)
   16419                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16420         [ #  # ]:          0 :         for (; i < resource->num_of_dest; i++)
   16421                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   16422                 :            :                                                    &resource->sample_idx[i]);
   16423                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], resource->idx);
   16424                 :          0 :         DRV_LOG(DEBUG, "destination array resource %p: removed",
   16425                 :            :                 (void *)resource);
   16426                 :          0 : }
   16427                 :            : 
   16428                 :            : /**
   16429                 :            :  * Release an destination array resource.
   16430                 :            :  *
   16431                 :            :  * @param dev
   16432                 :            :  *   Pointer to Ethernet device.
   16433                 :            :  * @param handle
   16434                 :            :  *   Pointer to mlx5_flow_handle.
   16435                 :            :  *
   16436                 :            :  * @return
   16437                 :            :  *   1 while a reference on it exists, 0 when freed.
   16438                 :            :  */
   16439                 :            : static int
   16440                 :          0 : flow_dv_dest_array_resource_release(struct rte_eth_dev *dev,
   16441                 :            :                                     struct mlx5_flow_handle *handle)
   16442                 :            : {
   16443                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16444                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   16445                 :            : 
   16446                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   16447                 :            :                                   handle->dvh.rix_dest_array);
   16448         [ #  # ]:          0 :         if (!resource)
   16449                 :            :                 return 0;
   16450                 :            :         MLX5_ASSERT(resource->action);
   16451                 :          0 :         return mlx5_list_unregister(priv->sh->dest_array_list,
   16452                 :            :                                     &resource->entry);
   16453                 :            : }
   16454                 :            : 
   16455                 :            : static void
   16456                 :          0 : flow_dev_geneve_tlv_option_resource_release(struct mlx5_dev_ctx_shared *sh)
   16457                 :            : {
   16458                 :          0 :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource =
   16459                 :            :                                 sh->geneve_tlv_option_resource;
   16460                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
   16461         [ #  # ]:          0 :         if (geneve_opt_resource) {
   16462         [ #  # ]:          0 :                 if (!(rte_atomic_fetch_sub_explicit(&geneve_opt_resource->refcnt, 1,
   16463                 :            :                                          rte_memory_order_relaxed) - 1)) {
   16464                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy
   16465                 :            :                                         (geneve_opt_resource->obj));
   16466                 :          0 :                         mlx5_free(sh->geneve_tlv_option_resource);
   16467                 :          0 :                         sh->geneve_tlv_option_resource = NULL;
   16468                 :            :                 }
   16469                 :            :         }
   16470                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
   16471                 :          0 : }
   16472                 :            : 
   16473                 :            : /**
   16474                 :            :  * Remove the flow from the NIC but keeps it in memory.
   16475                 :            :  * Lock free, (mutex should be acquired by caller).
   16476                 :            :  *
   16477                 :            :  * @param[in] dev
   16478                 :            :  *   Pointer to Ethernet device.
   16479                 :            :  * @param[in, out] flow
   16480                 :            :  *   Pointer to flow structure.
   16481                 :            :  */
   16482                 :            : static void
   16483                 :          0 : flow_dv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
   16484                 :            : {
   16485                 :            :         struct mlx5_flow_handle *dh;
   16486                 :            :         uint32_t handle_idx;
   16487                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16488                 :            : 
   16489         [ #  # ]:          0 :         if (!flow)
   16490                 :            :                 return;
   16491                 :          0 :         handle_idx = flow->dev_handles;
   16492         [ #  # ]:          0 :         while (handle_idx) {
   16493                 :          0 :                 dh = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   16494                 :            :                                     handle_idx);
   16495         [ #  # ]:          0 :                 if (!dh)
   16496                 :            :                         return;
   16497         [ #  # ]:          0 :                 if (dh->drv_flow) {
   16498                 :            :                         claim_zero(mlx5_flow_os_destroy_flow(dh->drv_flow));
   16499                 :          0 :                         dh->drv_flow = NULL;
   16500                 :            :                 }
   16501         [ #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE)
   16502                 :          0 :                         flow_dv_fate_resource_release(dev, dh);
   16503   [ #  #  #  # ]:          0 :                 if (dh->vf_vlan.tag && dh->vf_vlan.created)
   16504                 :          0 :                         mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
   16505                 :          0 :                 handle_idx = dh->next.next;
   16506                 :            :         }
   16507                 :            : }
   16508                 :            : 
   16509                 :            : /**
   16510                 :            :  * Remove the flow from the NIC and the memory.
   16511                 :            :  * Lock free, (mutex should be acquired by caller).
   16512                 :            :  *
   16513                 :            :  * @param[in] dev
   16514                 :            :  *   Pointer to the Ethernet device structure.
   16515                 :            :  * @param[in, out] flow
   16516                 :            :  *   Pointer to flow structure.
   16517                 :            :  */
   16518                 :            : static void
   16519                 :          0 : flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
   16520                 :            : {
   16521                 :            :         struct mlx5_flow_handle *dev_handle;
   16522                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16523                 :            :         struct mlx5_flow_meter_info *fm = NULL;
   16524                 :            :         uint32_t srss = 0;
   16525                 :            : 
   16526         [ #  # ]:          0 :         if (!flow)
   16527                 :            :                 return;
   16528                 :          0 :         flow_dv_remove(dev, flow);
   16529         [ #  # ]:          0 :         if (flow->counter) {
   16530                 :          0 :                 flow_dv_counter_free(dev, flow->counter);
   16531                 :          0 :                 flow->counter = 0;
   16532                 :            :         }
   16533         [ #  # ]:          0 :         if (flow->meter) {
   16534                 :          0 :                 fm = flow_dv_meter_find_by_idx(priv, flow->meter);
   16535         [ #  # ]:          0 :                 if (fm)
   16536                 :          0 :                         mlx5_flow_meter_detach(priv, fm);
   16537                 :          0 :                 flow->meter = 0;
   16538                 :            :         }
   16539                 :            :         /* Keep the current age handling by default. */
   16540   [ #  #  #  # ]:          0 :         if (flow->indirect_type == MLX5_INDIRECT_ACTION_TYPE_CT && flow->ct)
   16541                 :          0 :                 flow_dv_aso_ct_release(dev, flow->ct, NULL);
   16542         [ #  # ]:          0 :         else if (flow->age)
   16543                 :          0 :                 flow_dv_aso_age_release(dev, flow->age);
   16544         [ #  # ]:          0 :         while (flow->geneve_tlv_option) {
   16545                 :          0 :                 flow_dev_geneve_tlv_option_resource_release(priv->sh);
   16546                 :          0 :                 flow->geneve_tlv_option--;
   16547                 :            :         }
   16548         [ #  # ]:          0 :         while (flow->dev_handles) {
   16549                 :            :                 uint32_t tmp_idx = flow->dev_handles;
   16550                 :            : 
   16551                 :          0 :                 dev_handle = mlx5_ipool_get(priv->sh->ipool
   16552                 :            :                                             [MLX5_IPOOL_MLX5_FLOW], tmp_idx);
   16553         [ #  # ]:          0 :                 if (!dev_handle)
   16554                 :            :                         return;
   16555                 :          0 :                 flow->dev_handles = dev_handle->next.next;
   16556         [ #  # ]:          0 :                 while (dev_handle->flex_item) {
   16557                 :          0 :                         int index = rte_bsf32(dev_handle->flex_item);
   16558                 :            : 
   16559                 :          0 :                         mlx5_flex_release_index(dev, index);
   16560                 :          0 :                         dev_handle->flex_item &= ~(uint8_t)RTE_BIT32(index);
   16561                 :            :                 }
   16562         [ #  # ]:          0 :                 if (dev_handle->dvh.matcher)
   16563                 :          0 :                         flow_dv_matcher_release(dev, dev_handle);
   16564         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_sample)
   16565                 :          0 :                         flow_dv_sample_resource_release(dev, dev_handle);
   16566         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_dest_array)
   16567                 :          0 :                         flow_dv_dest_array_resource_release(dev, dev_handle);
   16568         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_encap_decap)
   16569                 :          0 :                         flow_encap_decap_resource_release(dev,
   16570                 :            :                                 dev_handle->dvh.rix_encap_decap);
   16571         [ #  # ]:          0 :                 if (dev_handle->dvh.modify_hdr)
   16572                 :            :                         flow_dv_modify_hdr_resource_release(dev, dev_handle);
   16573         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_push_vlan)
   16574                 :          0 :                         flow_dv_push_vlan_action_resource_release(dev,
   16575                 :            :                                                                   dev_handle);
   16576         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_tag)
   16577                 :          0 :                         flow_dv_tag_release(dev,
   16578                 :            :                                             dev_handle->dvh.rix_tag);
   16579         [ #  # ]:          0 :                 if (dev_handle->fate_action != MLX5_FLOW_FATE_SHARED_RSS)
   16580                 :          0 :                         flow_dv_fate_resource_release(dev, dev_handle);
   16581         [ #  # ]:          0 :                 else if (!srss)
   16582                 :          0 :                         srss = dev_handle->rix_srss;
   16583   [ #  #  #  # ]:          0 :                 if (fm && dev_handle->is_meter_flow_id &&
   16584         [ #  # ]:          0 :                     dev_handle->split_flow_id)
   16585                 :          0 :                         mlx5_ipool_free(fm->flow_ipool,
   16586                 :            :                                         dev_handle->split_flow_id);
   16587         [ #  # ]:          0 :                 else if (dev_handle->split_flow_id &&
   16588         [ #  # ]:          0 :                     !dev_handle->is_meter_flow_id)
   16589                 :          0 :                         mlx5_ipool_free(priv->sh->ipool
   16590                 :            :                                         [MLX5_IPOOL_RSS_EXPANTION_FLOW_ID],
   16591                 :            :                                         dev_handle->split_flow_id);
   16592                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   16593                 :            :                            tmp_idx);
   16594                 :            :         }
   16595         [ #  # ]:          0 :         if (srss)
   16596                 :          0 :                 flow_dv_shared_rss_action_release(dev, srss);
   16597                 :            : }
   16598                 :            : 
   16599                 :            : /**
   16600                 :            :  * Release array of hash RX queue objects.
   16601                 :            :  * Helper function.
   16602                 :            :  *
   16603                 :            :  * @param[in] dev
   16604                 :            :  *   Pointer to the Ethernet device structure.
   16605                 :            :  * @param[in, out] hrxqs
   16606                 :            :  *   Array of hash RX queue objects.
   16607                 :            :  *
   16608                 :            :  * @return
   16609                 :            :  *   Total number of references to hash RX queue objects in *hrxqs* array
   16610                 :            :  *   after this operation.
   16611                 :            :  */
   16612                 :            : static int
   16613                 :          0 : __flow_dv_hrxqs_release(struct rte_eth_dev *dev,
   16614                 :            :                         uint32_t (*hrxqs)[MLX5_RSS_HASH_FIELDS_LEN])
   16615                 :            : {
   16616                 :            :         size_t i;
   16617                 :            :         int remaining = 0;
   16618                 :            : 
   16619         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(*hrxqs); i++) {
   16620                 :          0 :                 int ret = mlx5_hrxq_release(dev, (*hrxqs)[i]);
   16621                 :            : 
   16622         [ #  # ]:          0 :                 if (!ret)
   16623                 :          0 :                         (*hrxqs)[i] = 0;
   16624                 :          0 :                 remaining += ret;
   16625                 :            :         }
   16626                 :          0 :         return remaining;
   16627                 :            : }
   16628                 :            : 
   16629                 :            : /**
   16630                 :            :  * Release all hash RX queue objects representing shared RSS action.
   16631                 :            :  *
   16632                 :            :  * @param[in] dev
   16633                 :            :  *   Pointer to the Ethernet device structure.
   16634                 :            :  * @param[in, out] action
   16635                 :            :  *   Shared RSS action to remove hash RX queue objects from.
   16636                 :            :  *
   16637                 :            :  * @return
   16638                 :            :  *   Total number of references to hash RX queue objects stored in *action*
   16639                 :            :  *   after this operation.
   16640                 :            :  *   Expected to be 0 if no external references held.
   16641                 :            :  */
   16642                 :            : static int
   16643                 :            : __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev,
   16644                 :            :                                  struct mlx5_shared_action_rss *shared_rss)
   16645                 :            : {
   16646                 :          0 :         return __flow_dv_hrxqs_release(dev, &shared_rss->hrxq);
   16647                 :            : }
   16648                 :            : 
   16649                 :            : /**
   16650                 :            :  * Adjust L3/L4 hash value of pre-created shared RSS hrxq according to
   16651                 :            :  * user input.
   16652                 :            :  *
   16653                 :            :  * Only one hash value is available for one L3+L4 combination:
   16654                 :            :  * for example:
   16655                 :            :  * MLX5_RSS_HASH_IPV4, MLX5_RSS_HASH_IPV4_SRC_ONLY, and
   16656                 :            :  * MLX5_RSS_HASH_IPV4_DST_ONLY are mutually exclusive so they can share
   16657                 :            :  * same slot in mlx5_rss_hash_fields.
   16658                 :            :  *
   16659                 :            :  * @param[in] orig_rss_types
   16660                 :            :  *   RSS type as provided in shared RSS action.
   16661                 :            :  * @param[in, out] hash_field
   16662                 :            :  *   hash_field variable needed to be adjusted.
   16663                 :            :  *
   16664                 :            :  * @return
   16665                 :            :  *   void
   16666                 :            :  */
   16667                 :            : void
   16668         [ #  # ]:          0 : flow_dv_action_rss_l34_hash_adjust(uint64_t orig_rss_types,
   16669                 :            :                                    uint64_t *hash_field)
   16670                 :            : {
   16671                 :            :         uint64_t rss_types = rte_eth_rss_hf_refine(orig_rss_types);
   16672                 :            : 
   16673   [ #  #  #  #  :          0 :         switch (*hash_field & ~IBV_RX_HASH_INNER) {
                      # ]
   16674                 :          0 :         case MLX5_RSS_HASH_IPV4:
   16675         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV4_LAYER_TYPES) {
   16676                 :          0 :                         *hash_field &= ~MLX5_RSS_HASH_IPV4;
   16677         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   16678                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_IPV4;
   16679         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   16680                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_IPV4;
   16681                 :            :                         else
   16682                 :          0 :                                 *hash_field |= MLX5_RSS_HASH_IPV4;
   16683                 :            :                 }
   16684                 :            :                 return;
   16685                 :          0 :         case MLX5_RSS_HASH_IPV6:
   16686         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV6_LAYER_TYPES) {
   16687                 :          0 :                         *hash_field &= ~MLX5_RSS_HASH_IPV6;
   16688         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   16689                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_IPV6;
   16690         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   16691                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_IPV6;
   16692                 :            :                         else
   16693                 :          0 :                                 *hash_field |= MLX5_RSS_HASH_IPV6;
   16694                 :            :                 }
   16695                 :            :                 return;
   16696                 :          0 :         case MLX5_RSS_HASH_IPV4_UDP:
   16697                 :            :                 /* fall-through. */
   16698                 :            :         case MLX5_RSS_HASH_IPV6_UDP:
   16699         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_UDP) {
   16700                 :          0 :                         *hash_field &= ~MLX5_UDP_IBV_RX_HASH;
   16701         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   16702                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_PORT_UDP;
   16703         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   16704                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_PORT_UDP;
   16705                 :            :                         else
   16706                 :          0 :                                 *hash_field |= MLX5_UDP_IBV_RX_HASH;
   16707                 :            :                 }
   16708                 :            :                 return;
   16709                 :          0 :         case MLX5_RSS_HASH_IPV4_TCP:
   16710                 :            :                 /* fall-through. */
   16711                 :            :         case MLX5_RSS_HASH_IPV6_TCP:
   16712         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_TCP) {
   16713                 :          0 :                         *hash_field &= ~MLX5_TCP_IBV_RX_HASH;
   16714         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   16715                 :          0 :                                 *hash_field |= IBV_RX_HASH_DST_PORT_TCP;
   16716         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   16717                 :          0 :                                 *hash_field |= IBV_RX_HASH_SRC_PORT_TCP;
   16718                 :            :                         else
   16719                 :          0 :                                 *hash_field |= MLX5_TCP_IBV_RX_HASH;
   16720                 :            :                 }
   16721                 :            :                 return;
   16722                 :            :         default:
   16723                 :            :                 return;
   16724                 :            :         }
   16725                 :            : }
   16726                 :            : 
   16727                 :            : /**
   16728                 :            :  * Setup shared RSS action.
   16729                 :            :  * Prepare set of hash RX queue objects sufficient to handle all valid
   16730                 :            :  * hash_fields combinations (see enum ibv_rx_hash_fields).
   16731                 :            :  *
   16732                 :            :  * @param[in] dev
   16733                 :            :  *   Pointer to the Ethernet device structure.
   16734                 :            :  * @param[in] action_idx
   16735                 :            :  *   Shared RSS action ipool index.
   16736                 :            :  * @param[in, out] action
   16737                 :            :  *   Partially initialized shared RSS action.
   16738                 :            :  * @param[out] error
   16739                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16740                 :            :  *   error only.
   16741                 :            :  *
   16742                 :            :  * @return
   16743                 :            :  *   0 on success, otherwise negative errno value.
   16744                 :            :  */
   16745                 :            : static int
   16746                 :          0 : __flow_dv_action_rss_setup(struct rte_eth_dev *dev,
   16747                 :            :                            uint32_t action_idx,
   16748                 :            :                            struct mlx5_shared_action_rss *shared_rss,
   16749                 :            :                            struct rte_flow_error *error)
   16750                 :            : {
   16751                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16752                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { 0 };
   16753                 :            :         size_t i;
   16754                 :            :         int err;
   16755                 :            : 
   16756                 :          0 :         shared_rss->ind_tbl = mlx5_ind_table_obj_new
   16757                 :            :                               (dev, shared_rss->origin.queue,
   16758                 :            :                                shared_rss->origin.queue_num,
   16759                 :            :                                true,
   16760                 :          0 :                                !!dev->data->dev_started);
   16761         [ #  # ]:          0 :         if (!shared_rss->ind_tbl)
   16762                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   16763                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16764                 :            :                                           "cannot setup indirection table");
   16765                 :          0 :         memcpy(rss_desc.key, shared_rss->origin.key, MLX5_RSS_HASH_KEY_LEN);
   16766                 :          0 :         rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN;
   16767                 :          0 :         rss_desc.symmetric_hash_function =
   16768                 :          0 :                 MLX5_RSS_IS_SYMM(shared_rss->origin.func);
   16769                 :          0 :         rss_desc.const_q = shared_rss->origin.queue;
   16770                 :          0 :         rss_desc.queue_num = shared_rss->origin.queue_num;
   16771                 :            :         /* Set non-zero value to indicate a shared RSS. */
   16772                 :          0 :         rss_desc.shared_rss = action_idx;
   16773                 :          0 :         rss_desc.ind_tbl = shared_rss->ind_tbl;
   16774         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
   16775                 :          0 :                 rss_desc.hws_flags = MLX5DR_ACTION_FLAG_HWS_RX;
   16776         [ #  # ]:          0 :         for (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) {
   16777                 :            :                 struct mlx5_hrxq *hrxq;
   16778                 :          0 :                 uint64_t hash_fields = mlx5_rss_hash_fields[i];
   16779                 :            :                 int tunnel = 0;
   16780                 :            : 
   16781                 :          0 :                 flow_dv_action_rss_l34_hash_adjust(shared_rss->origin.types,
   16782                 :            :                                                    &hash_fields);
   16783         [ #  # ]:          0 :                 if (shared_rss->origin.level > 1) {
   16784                 :          0 :                         hash_fields |= IBV_RX_HASH_INNER;
   16785                 :            :                         tunnel = 1;
   16786                 :            :                 }
   16787                 :          0 :                 rss_desc.tunnel = tunnel;
   16788                 :          0 :                 rss_desc.hash_fields = hash_fields;
   16789                 :          0 :                 hrxq = mlx5_hrxq_get(dev, &rss_desc);
   16790         [ #  # ]:          0 :                 if (!hrxq) {
   16791                 :          0 :                         rte_flow_error_set
   16792                 :            :                                 (error, rte_errno,
   16793                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16794                 :            :                                  "cannot get hash queue");
   16795                 :          0 :                         goto error_hrxq_new;
   16796                 :            :                 }
   16797                 :          0 :                 err = __flow_dv_action_rss_hrxq_set
   16798                 :            :                         (shared_rss, hash_fields, hrxq->idx);
   16799                 :            :                 MLX5_ASSERT(!err);
   16800                 :            :         }
   16801                 :            :         return 0;
   16802                 :            : error_hrxq_new:
   16803                 :          0 :         err = rte_errno;
   16804                 :            :         __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
   16805         [ #  # ]:          0 :         if (!mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true))
   16806                 :          0 :                 shared_rss->ind_tbl = NULL;
   16807                 :          0 :         rte_errno = err;
   16808                 :          0 :         return -rte_errno;
   16809                 :            : }
   16810                 :            : 
   16811                 :            : /**
   16812                 :            :  * Create shared RSS action.
   16813                 :            :  *
   16814                 :            :  * @param[in] dev
   16815                 :            :  *   Pointer to the Ethernet device structure.
   16816                 :            :  * @param[in] conf
   16817                 :            :  *   Shared action configuration.
   16818                 :            :  * @param[in] rss
   16819                 :            :  *   RSS action specification used to create shared action.
   16820                 :            :  * @param[out] error
   16821                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16822                 :            :  *   error only.
   16823                 :            :  *
   16824                 :            :  * @return
   16825                 :            :  *   A valid shared action ID in case of success, 0 otherwise and
   16826                 :            :  *   rte_errno is set.
   16827                 :            :  */
   16828                 :            : static uint32_t
   16829                 :          0 : __flow_dv_action_rss_create(struct rte_eth_dev *dev,
   16830                 :            :                             const struct rte_flow_indir_action_conf *conf,
   16831                 :            :                             const struct rte_flow_action_rss *rss,
   16832                 :            :                             struct rte_flow_error *error)
   16833                 :            : {
   16834                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16835                 :            :         struct mlx5_shared_action_rss *shared_rss = NULL;
   16836                 :            :         struct rte_flow_action_rss *origin;
   16837                 :            :         const uint8_t *rss_key;
   16838                 :            :         uint32_t idx;
   16839                 :            : 
   16840                 :            :         RTE_SET_USED(conf);
   16841                 :          0 :         shared_rss = mlx5_ipool_zmalloc
   16842                 :          0 :                          (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], &idx);
   16843         [ #  # ]:          0 :         if (!shared_rss) {
   16844                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   16845                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16846                 :            :                                    "cannot allocate resource memory");
   16847                 :          0 :                 goto error_rss_init;
   16848                 :            :         }
   16849         [ #  # ]:          0 :         if (idx > (1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET)) {
   16850                 :          0 :                 rte_flow_error_set(error, E2BIG,
   16851                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16852                 :            :                                    "rss action number out of range");
   16853                 :          0 :                 goto error_rss_init;
   16854                 :            :         }
   16855                 :            :         origin = &shared_rss->origin;
   16856                 :          0 :         origin->func = rss->func;
   16857                 :          0 :         origin->level = rss->level;
   16858                 :            :         /* RSS type 0 indicates default RSS type (RTE_ETH_RSS_IP). */
   16859         [ #  # ]:          0 :         origin->types = !rss->types ? RTE_ETH_RSS_IP : rss->types;
   16860                 :            :         /* NULL RSS key indicates default RSS key. */
   16861         [ #  # ]:          0 :         rss_key = !rss->key ? rss_hash_default_key : rss->key;
   16862                 :          0 :         memcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   16863                 :          0 :         origin->key = &shared_rss->key[0];
   16864                 :          0 :         origin->key_len = MLX5_RSS_HASH_KEY_LEN;
   16865                 :          0 :         origin->queue = rss->queue;
   16866                 :          0 :         origin->queue_num = rss->queue_num;
   16867         [ #  # ]:          0 :         if (__flow_dv_action_rss_setup(dev, idx, shared_rss, error))
   16868                 :          0 :                 goto error_rss_init;
   16869                 :            :         /* Update queue with indirect table queue memoyr. */
   16870                 :          0 :         origin->queue = shared_rss->ind_tbl->queues;
   16871                 :            :         rte_spinlock_init(&shared_rss->action_rss_sl);
   16872                 :          0 :         rte_atomic_fetch_add_explicit(&shared_rss->refcnt, 1, rte_memory_order_relaxed);
   16873                 :          0 :         rte_spinlock_lock(&priv->shared_act_sl);
   16874   [ #  #  #  # ]:          0 :         ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16875                 :            :                      &priv->rss_shared_actions, idx, shared_rss, next);
   16876                 :            :         rte_spinlock_unlock(&priv->shared_act_sl);
   16877                 :          0 :         return idx;
   16878                 :          0 : error_rss_init:
   16879         [ #  # ]:          0 :         if (shared_rss) {
   16880         [ #  # ]:          0 :                 if (shared_rss->ind_tbl)
   16881                 :          0 :                         mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl,
   16882                 :          0 :                                                    !!dev->data->dev_started);
   16883                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16884                 :            :                                 idx);
   16885                 :            :         }
   16886                 :            :         return 0;
   16887                 :            : }
   16888                 :            : 
   16889                 :            : /**
   16890                 :            :  * Destroy the shared RSS action.
   16891                 :            :  * Release related hash RX queue objects.
   16892                 :            :  *
   16893                 :            :  * @param[in] dev
   16894                 :            :  *   Pointer to the Ethernet device structure.
   16895                 :            :  * @param[in] idx
   16896                 :            :  *   The shared RSS action object ID to be removed.
   16897                 :            :  * @param[out] error
   16898                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16899                 :            :  *   error only.
   16900                 :            :  *
   16901                 :            :  * @return
   16902                 :            :  *   0 on success, otherwise negative errno value.
   16903                 :            :  */
   16904                 :            : static int
   16905                 :          0 : __flow_dv_action_rss_release(struct rte_eth_dev *dev, uint32_t idx,
   16906                 :            :                              struct rte_flow_error *error)
   16907                 :            : {
   16908                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16909                 :            :         struct mlx5_shared_action_rss *shared_rss =
   16910                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   16911                 :            :         uint32_t old_refcnt = 1;
   16912                 :            :         int remaining;
   16913                 :            : 
   16914         [ #  # ]:          0 :         if (!shared_rss)
   16915                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   16916                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   16917                 :            :                                           "invalid shared action");
   16918         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&shared_rss->refcnt, &old_refcnt,
   16919                 :            :                                          0, rte_memory_order_acquire,
   16920                 :            :                                          rte_memory_order_relaxed))
   16921                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16922                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16923                 :            :                                           NULL,
   16924                 :            :                                           "shared rss has references");
   16925                 :            :         remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
   16926         [ #  # ]:          0 :         if (remaining)
   16927                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16928                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16929                 :            :                                           NULL,
   16930                 :            :                                           "shared rss hrxq has references");
   16931                 :          0 :         remaining = mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl,
   16932                 :          0 :                                                !!dev->data->dev_started);
   16933         [ #  # ]:          0 :         if (remaining)
   16934                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   16935                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   16936                 :            :                                           NULL,
   16937                 :            :                                           "shared rss indirection table has"
   16938                 :            :                                           " references");
   16939                 :          0 :         rte_spinlock_lock(&priv->shared_act_sl);
   16940   [ #  #  #  #  :          0 :         ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
          #  #  #  #  #  
                      # ]
   16941                 :            :                      &priv->rss_shared_actions, idx, shared_rss, next);
   16942                 :            :         rte_spinlock_unlock(&priv->shared_act_sl);
   16943                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   16944                 :            :                         idx);
   16945                 :          0 :         return 0;
   16946                 :            : }
   16947                 :            : 
   16948                 :            : /**
   16949                 :            :  * Create indirect action, lock free,
   16950                 :            :  * (mutex should be acquired by caller).
   16951                 :            :  * Dispatcher for action type specific call.
   16952                 :            :  *
   16953                 :            :  * @param[in] dev
   16954                 :            :  *   Pointer to the Ethernet device structure.
   16955                 :            :  * @param[in] conf
   16956                 :            :  *   Shared action configuration.
   16957                 :            :  * @param[in] action
   16958                 :            :  *   Action specification used to create indirect action.
   16959                 :            :  * @param[out] error
   16960                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16961                 :            :  *   error only.
   16962                 :            :  *
   16963                 :            :  * @return
   16964                 :            :  *   A valid shared action handle in case of success, NULL otherwise and
   16965                 :            :  *   rte_errno is set.
   16966                 :            :  */
   16967                 :            : struct rte_flow_action_handle *
   16968                 :          0 : flow_dv_action_create(struct rte_eth_dev *dev,
   16969                 :            :                       const struct rte_flow_indir_action_conf *conf,
   16970                 :            :                       const struct rte_flow_action *action,
   16971                 :            :                       struct rte_flow_error *err)
   16972                 :            : {
   16973                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16974                 :            :         uint32_t age_idx = 0;
   16975                 :            :         uint32_t idx = 0;
   16976                 :            :         uint32_t ret = 0;
   16977                 :            : 
   16978   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   16979                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   16980                 :          0 :                 ret = __flow_dv_action_rss_create(dev, conf, action->conf, err);
   16981                 :            :                 idx = (MLX5_INDIRECT_ACTION_TYPE_RSS <<
   16982                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | ret;
   16983                 :          0 :                 break;
   16984                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   16985                 :          0 :                 age_idx = flow_dv_aso_age_alloc(dev, err);
   16986         [ #  # ]:          0 :                 if (!age_idx) {
   16987                 :          0 :                         ret = -rte_errno;
   16988                 :          0 :                         break;
   16989                 :            :                 }
   16990                 :          0 :                 idx = (MLX5_INDIRECT_ACTION_TYPE_AGE <<
   16991                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | age_idx;
   16992                 :          0 :                 flow_dv_aso_age_params_init(dev, age_idx,
   16993                 :            :                                         ((const struct rte_flow_action_age *)
   16994                 :          0 :                                                 action->conf)->context ?
   16995                 :            :                                         ((const struct rte_flow_action_age *)
   16996                 :            :                                                 action->conf)->context :
   16997                 :          0 :                                         (void *)(uintptr_t)idx,
   16998                 :            :                                         ((const struct rte_flow_action_age *)
   16999         [ #  # ]:          0 :                                                 action->conf)->timeout);
   17000                 :            :                 ret = age_idx;
   17001                 :          0 :                 break;
   17002                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   17003                 :          0 :                 ret = flow_dv_translate_create_counter(dev, NULL, NULL, NULL);
   17004                 :          0 :                 idx = (MLX5_INDIRECT_ACTION_TYPE_COUNT <<
   17005                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | ret;
   17006                 :          0 :                 break;
   17007                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   17008                 :          0 :                 ret = flow_dv_translate_create_conntrack(dev, action->conf,
   17009                 :            :                                                          err);
   17010         [ #  # ]:          0 :                 if (!ret)
   17011                 :            :                         break;
   17012                 :          0 :                 idx = MLX5_INDIRECT_ACT_CT_GEN_IDX(PORT_ID(priv), ret);
   17013                 :          0 :                 break;
   17014                 :          0 :         default:
   17015                 :          0 :                 rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   17016                 :            :                                    NULL, "action type not supported");
   17017                 :            :                 break;
   17018                 :            :         }
   17019         [ #  # ]:          0 :         return ret ? (struct rte_flow_action_handle *)(uintptr_t)idx : NULL;
   17020                 :            : }
   17021                 :            : 
   17022                 :            : /**
   17023                 :            :  * Destroy the indirect action.
   17024                 :            :  * Release action related resources on the NIC and the memory.
   17025                 :            :  * Lock free, (mutex should be acquired by caller).
   17026                 :            :  * Dispatcher for action type specific call.
   17027                 :            :  *
   17028                 :            :  * @param[in] dev
   17029                 :            :  *   Pointer to the Ethernet device structure.
   17030                 :            :  * @param[in] handle
   17031                 :            :  *   The indirect action object handle to be removed.
   17032                 :            :  * @param[out] error
   17033                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17034                 :            :  *   error only.
   17035                 :            :  *
   17036                 :            :  * @return
   17037                 :            :  *   0 on success, otherwise negative errno value.
   17038                 :            :  */
   17039                 :            : int
   17040                 :          0 : flow_dv_action_destroy(struct rte_eth_dev *dev,
   17041                 :            :                        struct rte_flow_action_handle *handle,
   17042                 :            :                        struct rte_flow_error *error)
   17043                 :            : {
   17044                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   17045                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   17046                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   17047                 :            :         struct mlx5_flow_counter *cnt;
   17048                 :            :         uint32_t no_flow_refcnt = 1;
   17049                 :            :         int ret;
   17050                 :            : 
   17051   [ #  #  #  #  :          0 :         switch (type) {
                      # ]
   17052                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   17053                 :          0 :                 return __flow_dv_action_rss_release(dev, idx, error);
   17054                 :            :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   17055                 :            :                 cnt = flow_dv_counter_get_by_idx(dev, idx, NULL);
   17056         [ #  # ]:          0 :                 if (!rte_atomic_compare_exchange_strong_explicit(&cnt->shared_info.refcnt,
   17057                 :            :                                                  &no_flow_refcnt, 1,
   17058                 :            :                                                  rte_memory_order_acquire,
   17059                 :            :                                                  rte_memory_order_relaxed))
   17060                 :          0 :                         return rte_flow_error_set(error, EBUSY,
   17061                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   17062                 :            :                                                   NULL,
   17063                 :            :                                                   "Indirect count action has references");
   17064                 :          0 :                 flow_dv_counter_free(dev, idx);
   17065                 :          0 :                 return 0;
   17066                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   17067                 :          0 :                 ret = flow_dv_aso_age_release(dev, idx);
   17068         [ #  # ]:          0 :                 if (ret)
   17069                 :            :                         /*
   17070                 :            :                          * In this case, the last flow has a reference will
   17071                 :            :                          * actually release the age action.
   17072                 :            :                          */
   17073                 :          0 :                         DRV_LOG(DEBUG, "Indirect age action %" PRIu32 " was"
   17074                 :            :                                 " released with references %d.", idx, ret);
   17075                 :            :                 return 0;
   17076                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   17077                 :          0 :                 ret = flow_dv_aso_ct_release(dev, idx, error);
   17078         [ #  # ]:          0 :                 if (ret < 0)
   17079                 :            :                         return ret;
   17080         [ #  # ]:          0 :                 if (ret > 0)
   17081                 :          0 :                         DRV_LOG(DEBUG, "Connection tracking object %u still "
   17082                 :            :                                 "has references %d.", idx, ret);
   17083                 :            :                 return 0;
   17084                 :          0 :         default:
   17085                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17086                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17087                 :            :                                           NULL,
   17088                 :            :                                           "action type not supported");
   17089                 :            :         }
   17090                 :            : }
   17091                 :            : 
   17092                 :            : /**
   17093                 :            :  * Updates in place shared RSS action configuration.
   17094                 :            :  *
   17095                 :            :  * @param[in] dev
   17096                 :            :  *   Pointer to the Ethernet device structure.
   17097                 :            :  * @param[in] idx
   17098                 :            :  *   The shared RSS action object ID to be updated.
   17099                 :            :  * @param[in] action_conf
   17100                 :            :  *   RSS action specification used to modify *shared_rss*.
   17101                 :            :  * @param[out] error
   17102                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17103                 :            :  *   error only.
   17104                 :            :  *
   17105                 :            :  * @return
   17106                 :            :  *   0 on success, otherwise negative errno value.
   17107                 :            :  * @note: currently only support update of RSS queues.
   17108                 :            :  */
   17109                 :            : static int
   17110                 :          0 : __flow_dv_action_rss_update(struct rte_eth_dev *dev, uint32_t idx,
   17111                 :            :                             const struct rte_flow_action_rss *action_conf,
   17112                 :            :                             struct rte_flow_error *error)
   17113                 :            : {
   17114                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17115                 :            :         struct mlx5_shared_action_rss *shared_rss =
   17116                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   17117                 :            :         int ret = 0;
   17118                 :            :         void *queue = NULL;
   17119                 :            :         void *queue_i = NULL;
   17120                 :          0 :         uint32_t queue_size = action_conf->queue_num * sizeof(uint16_t);
   17121                 :          0 :         bool dev_started = !!dev->data->dev_started;
   17122                 :            : 
   17123         [ #  # ]:          0 :         if (!shared_rss)
   17124                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   17125                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17126                 :            :                                           "invalid shared action to update");
   17127         [ #  # ]:          0 :         if (priv->obj_ops.ind_table_modify == NULL)
   17128                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17129                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17130                 :            :                                           "cannot modify indirection table");
   17131                 :          0 :         queue = mlx5_malloc(MLX5_MEM_ZERO,
   17132                 :          0 :                             RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
   17133                 :            :                             0, SOCKET_ID_ANY);
   17134         [ #  # ]:          0 :         if (!queue)
   17135                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   17136                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17137                 :            :                                           NULL,
   17138                 :            :                                           "cannot allocate resource memory");
   17139                 :          0 :         memcpy(queue, action_conf->queue, queue_size);
   17140                 :            :         MLX5_ASSERT(shared_rss->ind_tbl);
   17141                 :          0 :         rte_spinlock_lock(&shared_rss->action_rss_sl);
   17142                 :          0 :         queue_i = shared_rss->ind_tbl->queues;
   17143                 :          0 :         ret = mlx5_ind_table_obj_modify(dev, shared_rss->ind_tbl,
   17144                 :          0 :                                         queue, action_conf->queue_num,
   17145                 :            :                                         true /* standalone */,
   17146                 :            :                                         dev_started /* ref_new_qs */,
   17147                 :            :                                         dev_started /* deref_old_qs */);
   17148         [ #  # ]:          0 :         if (ret) {
   17149                 :          0 :                 ret = rte_flow_error_set(error, rte_errno,
   17150                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17151                 :            :                                           "cannot update indirection table");
   17152                 :            :         } else {
   17153                 :            :                 /* Restore the queue to indirect table internal queue. */
   17154                 :            :                 memcpy(queue_i, queue, queue_size);
   17155                 :          0 :                 shared_rss->ind_tbl->queues = queue_i;
   17156                 :          0 :                 shared_rss->origin.queue_num = action_conf->queue_num;
   17157                 :            :         }
   17158                 :          0 :         mlx5_free(queue);
   17159                 :            :         rte_spinlock_unlock(&shared_rss->action_rss_sl);
   17160                 :          0 :         return ret;
   17161                 :            : }
   17162                 :            : 
   17163                 :            : /*
   17164                 :            :  * Updates in place conntrack context or direction.
   17165                 :            :  * Context update should be synchronized.
   17166                 :            :  *
   17167                 :            :  * @param[in] dev
   17168                 :            :  *   Pointer to the Ethernet device structure.
   17169                 :            :  * @param[in] idx
   17170                 :            :  *   The conntrack object ID to be updated.
   17171                 :            :  * @param[in] update
   17172                 :            :  *   Pointer to the structure of information to update.
   17173                 :            :  * @param[out] error
   17174                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17175                 :            :  *   error only.
   17176                 :            :  *
   17177                 :            :  * @return
   17178                 :            :  *   0 on success, otherwise negative errno value.
   17179                 :            :  */
   17180                 :            : static int
   17181                 :          0 : __flow_dv_action_ct_update(struct rte_eth_dev *dev, uint32_t idx,
   17182                 :            :                            const struct rte_flow_modify_conntrack *update,
   17183                 :            :                            struct rte_flow_error *error)
   17184                 :            : {
   17185                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17186                 :            :         struct mlx5_aso_ct_action *ct;
   17187                 :            :         const struct rte_flow_action_conntrack *new_prf;
   17188                 :            :         int ret = 0;
   17189                 :          0 :         uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(idx);
   17190                 :            :         uint32_t dev_idx;
   17191                 :            : 
   17192         [ #  # ]:          0 :         if (PORT_ID(priv) != owner)
   17193                 :          0 :                 return rte_flow_error_set(error, EACCES,
   17194                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17195                 :            :                                           NULL,
   17196                 :            :                                           "CT object owned by another port");
   17197                 :          0 :         dev_idx = MLX5_INDIRECT_ACT_CT_GET_IDX(idx);
   17198                 :          0 :         ct = flow_aso_ct_get_by_dev_idx(dev, dev_idx);
   17199         [ #  # ]:          0 :         if (!ct->refcnt)
   17200                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   17201                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17202                 :            :                                           NULL,
   17203                 :            :                                           "CT object is inactive");
   17204                 :          0 :         new_prf = &update->new_ct;
   17205         [ #  # ]:          0 :         if (update->direction)
   17206                 :          0 :                 ct->is_original = !!new_prf->is_original_dir;
   17207         [ #  # ]:          0 :         if (update->state) {
   17208                 :            :                 /* Only validate the profile when it needs to be updated. */
   17209                 :          0 :                 ret = mlx5_validate_action_ct(dev, new_prf, error);
   17210         [ #  # ]:          0 :                 if (ret)
   17211                 :            :                         return ret;
   17212                 :          0 :                 ret = mlx5_aso_ct_update_by_wqe(priv->sh, MLX5_HW_INV_QUEUE,
   17213                 :            :                                                 ct, new_prf, NULL, true);
   17214         [ #  # ]:          0 :                 if (ret)
   17215                 :          0 :                         return rte_flow_error_set(error, EIO,
   17216                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17217                 :            :                                         NULL,
   17218                 :            :                                         "Failed to send CT context update WQE");
   17219                 :            :                 /* Block until ready or a failure, default is asynchronous. */
   17220                 :          0 :                 ret = mlx5_aso_ct_available(priv->sh, MLX5_HW_INV_QUEUE, ct);
   17221         [ #  # ]:          0 :                 if (ret)
   17222                 :          0 :                         rte_flow_error_set(error, rte_errno,
   17223                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17224                 :            :                                            NULL,
   17225                 :            :                                            "Timeout to get the CT update");
   17226                 :            :         }
   17227                 :            :         return ret;
   17228                 :            : }
   17229                 :            : 
   17230                 :            : /**
   17231                 :            :  * Updates in place shared action configuration, lock free,
   17232                 :            :  * (mutex should be acquired by caller).
   17233                 :            :  *
   17234                 :            :  * @param[in] dev
   17235                 :            :  *   Pointer to the Ethernet device structure.
   17236                 :            :  * @param[in] handle
   17237                 :            :  *   The indirect action object handle to be updated.
   17238                 :            :  * @param[in] update
   17239                 :            :  *   Action specification used to modify the action pointed by *handle*.
   17240                 :            :  *   *update* could be of same type with the action pointed by the *handle*
   17241                 :            :  *   handle argument, or some other structures like a wrapper, depending on
   17242                 :            :  *   the indirect action type.
   17243                 :            :  * @param[out] error
   17244                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17245                 :            :  *   error only.
   17246                 :            :  *
   17247                 :            :  * @return
   17248                 :            :  *   0 on success, otherwise negative errno value.
   17249                 :            :  */
   17250                 :            : int
   17251                 :          0 : flow_dv_action_update(struct rte_eth_dev *dev,
   17252                 :            :                         struct rte_flow_action_handle *handle,
   17253                 :            :                         const void *update,
   17254                 :            :                         struct rte_flow_error *err)
   17255                 :            : {
   17256                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   17257                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   17258                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   17259                 :            :         const void *action_conf;
   17260                 :            : 
   17261      [ #  #  # ]:          0 :         switch (type) {
   17262                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   17263                 :          0 :                 action_conf = ((const struct rte_flow_action *)update)->conf;
   17264                 :          0 :                 return __flow_dv_action_rss_update(dev, idx, action_conf, err);
   17265                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   17266                 :          0 :                 return __flow_dv_action_ct_update(dev, idx, update, err);
   17267                 :          0 :         default:
   17268                 :          0 :                 return rte_flow_error_set(err, ENOTSUP,
   17269                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17270                 :            :                                           NULL,
   17271                 :            :                                           "action type update not supported");
   17272                 :            :         }
   17273                 :            : }
   17274                 :            : 
   17275                 :            : /**
   17276                 :            :  * Destroy the meter sub policy table rules.
   17277                 :            :  * Lock free, (mutex should be acquired by caller).
   17278                 :            :  *
   17279                 :            :  * @param[in] dev
   17280                 :            :  *   Pointer to Ethernet device.
   17281                 :            :  * @param[in] sub_policy
   17282                 :            :  *   Pointer to meter sub policy table.
   17283                 :            :  */
   17284                 :            : static void
   17285                 :          0 : __flow_dv_destroy_sub_policy_rules(struct rte_eth_dev *dev,
   17286                 :            :                              struct mlx5_flow_meter_sub_policy *sub_policy)
   17287                 :            : {
   17288                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17289                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   17290                 :          0 :         struct mlx5_flow_meter_policy *policy = sub_policy->main_policy;
   17291                 :            :         struct mlx5_flow_meter_info *next_fm;
   17292                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   17293                 :            :         void *tmp;
   17294                 :            :         uint32_t i;
   17295                 :            : 
   17296         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   17297                 :            :                 next_fm = NULL;
   17298         [ #  # ]:          0 :                 if (i <= RTE_COLOR_YELLOW && policy &&
   17299         [ #  # ]:          0 :                     policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR)
   17300                 :          0 :                         next_fm = mlx5_flow_meter_find(priv,
   17301                 :            :                                         policy->act_cnt[i].next_mtr_id, NULL);
   17302         [ #  # ]:          0 :                 RTE_TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
   17303                 :            :                                    next_port, tmp) {
   17304                 :          0 :                         claim_zero(mlx5_flow_os_destroy_flow(color_rule->rule));
   17305                 :          0 :                         tbl = container_of(color_rule->matcher->tbl,
   17306                 :            :                                            typeof(*tbl), tbl);
   17307                 :          0 :                         mlx5_list_unregister(tbl->matchers,
   17308                 :            :                                              &color_rule->matcher->entry);
   17309         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[i],
   17310                 :            :                                      color_rule, next_port);
   17311                 :          0 :                         mlx5_free(color_rule);
   17312         [ #  # ]:          0 :                         if (next_fm)
   17313                 :          0 :                                 mlx5_flow_meter_detach(priv, next_fm);
   17314                 :            :                 }
   17315                 :            :         }
   17316         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   17317         [ #  # ]:          0 :                 if (sub_policy->rix_hrxq[i]) {
   17318   [ #  #  #  # ]:          0 :                         if (policy && !policy->is_hierarchy)
   17319                 :          0 :                                 mlx5_hrxq_release(dev, sub_policy->rix_hrxq[i]);
   17320                 :          0 :                         sub_policy->rix_hrxq[i] = 0;
   17321                 :            :                 }
   17322         [ #  # ]:          0 :                 if (sub_policy->jump_tbl[i]) {
   17323                 :          0 :                         flow_dv_tbl_resource_release(MLX5_SH(dev),
   17324                 :            :                                                      sub_policy->jump_tbl[i]);
   17325                 :          0 :                         sub_policy->jump_tbl[i] = NULL;
   17326                 :            :                 }
   17327                 :            :         }
   17328         [ #  # ]:          0 :         if (sub_policy->tbl_rsc) {
   17329                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev),
   17330                 :            :                                              sub_policy->tbl_rsc);
   17331                 :          0 :                 sub_policy->tbl_rsc = NULL;
   17332                 :            :         }
   17333                 :          0 : }
   17334                 :            : 
   17335                 :            : /**
   17336                 :            :  * Destroy policy rules, lock free,
   17337                 :            :  * (mutex should be acquired by caller).
   17338                 :            :  * Dispatcher for action type specific call.
   17339                 :            :  *
   17340                 :            :  * @param[in] dev
   17341                 :            :  *   Pointer to the Ethernet device structure.
   17342                 :            :  * @param[in] mtr_policy
   17343                 :            :  *   Meter policy struct.
   17344                 :            :  */
   17345                 :            : static void
   17346                 :          0 : flow_dv_destroy_policy_rules(struct rte_eth_dev *dev,
   17347                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
   17348                 :            : {
   17349                 :            :         uint32_t i, j;
   17350                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   17351                 :            :         uint16_t sub_policy_num;
   17352                 :            : 
   17353         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   17354                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   17355                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   17356                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   17357         [ #  # ]:          0 :                 for (j = 0; j < sub_policy_num; j++) {
   17358                 :          0 :                         sub_policy = mtr_policy->sub_policys[i][j];
   17359         [ #  # ]:          0 :                         if (sub_policy)
   17360                 :          0 :                                 __flow_dv_destroy_sub_policy_rules(dev,
   17361                 :            :                                                                    sub_policy);
   17362                 :            :                 }
   17363                 :            :         }
   17364                 :          0 : }
   17365                 :            : 
   17366                 :            : /**
   17367                 :            :  * Destroy policy action, lock free,
   17368                 :            :  * (mutex should be acquired by caller).
   17369                 :            :  * Dispatcher for action type specific call.
   17370                 :            :  *
   17371                 :            :  * @param[in] dev
   17372                 :            :  *   Pointer to the Ethernet device structure.
   17373                 :            :  * @param[in] mtr_policy
   17374                 :            :  *   Meter policy struct.
   17375                 :            :  */
   17376                 :            : static void
   17377                 :          0 : flow_dv_destroy_mtr_policy_acts(struct rte_eth_dev *dev,
   17378                 :            :                       struct mlx5_flow_meter_policy *mtr_policy)
   17379                 :            : {
   17380                 :            :         struct rte_flow_action *rss_action;
   17381                 :            :         struct mlx5_flow_handle dev_handle;
   17382                 :            :         uint32_t i, j;
   17383                 :            : 
   17384         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   17385         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].rix_mark) {
   17386                 :          0 :                         flow_dv_tag_release(dev,
   17387                 :            :                                 mtr_policy->act_cnt[i].rix_mark);
   17388                 :          0 :                         mtr_policy->act_cnt[i].rix_mark = 0;
   17389                 :            :                 }
   17390         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].modify_hdr) {
   17391                 :            :                         dev_handle.dvh.modify_hdr =
   17392                 :            :                                 mtr_policy->act_cnt[i].modify_hdr;
   17393                 :            :                         flow_dv_modify_hdr_resource_release(dev, &dev_handle);
   17394                 :            :                 }
   17395   [ #  #  #  # ]:          0 :                 switch (mtr_policy->act_cnt[i].fate_action) {
   17396                 :          0 :                 case MLX5_FLOW_FATE_SHARED_RSS:
   17397                 :          0 :                         rss_action = mtr_policy->act_cnt[i].rss;
   17398                 :          0 :                         mlx5_free(rss_action);
   17399                 :          0 :                         break;
   17400                 :          0 :                 case MLX5_FLOW_FATE_PORT_ID:
   17401         [ #  # ]:          0 :                         if (mtr_policy->act_cnt[i].rix_port_id_action) {
   17402                 :          0 :                                 flow_dv_port_id_action_resource_release(dev,
   17403                 :            :                                 mtr_policy->act_cnt[i].rix_port_id_action);
   17404                 :          0 :                                 mtr_policy->act_cnt[i].rix_port_id_action = 0;
   17405                 :            :                         }
   17406                 :            :                         break;
   17407                 :            :                 case MLX5_FLOW_FATE_DROP:
   17408                 :            :                 case MLX5_FLOW_FATE_JUMP:
   17409         [ #  # ]:          0 :                         for (j = 0; j < MLX5_MTR_DOMAIN_MAX; j++)
   17410                 :          0 :                                 mtr_policy->act_cnt[i].dr_jump_action[j] =
   17411                 :            :                                                 NULL;
   17412                 :            :                         break;
   17413                 :            :                 default:
   17414                 :            :                         /*Queue action do nothing*/
   17415                 :            :                         break;
   17416                 :            :                 }
   17417                 :            :         }
   17418         [ #  # ]:          0 :         for (j = 0; j < MLX5_MTR_DOMAIN_MAX; j++)
   17419                 :          0 :                 mtr_policy->dr_drop_action[j] = NULL;
   17420                 :          0 : }
   17421                 :            : 
   17422                 :            : /**
   17423                 :            :  * Create yellow action for color aware meter.
   17424                 :            :  *
   17425                 :            :  * @param[in] dev
   17426                 :            :  *   Pointer to the Ethernet device structure.
   17427                 :            :  * @param[in] fm
   17428                 :            :  *   Meter information table.
   17429                 :            :  * @param[out] error
   17430                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17431                 :            :  *   error only.
   17432                 :            :  *
   17433                 :            :  * @return
   17434                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   17435                 :            :  */
   17436                 :            : static int
   17437                 :          0 : __flow_dv_create_mtr_yellow_action(struct rte_eth_dev *dev,
   17438                 :            :                                    struct mlx5_flow_meter_info *fm,
   17439                 :            :                                    struct rte_mtr_error *error)
   17440                 :            : {
   17441                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
   17442                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17443                 :            :         struct rte_flow_error flow_err;
   17444                 :            :         struct mlx5_aso_mtr *aso_mtr;
   17445                 :            :         struct mlx5_aso_mtr_pool *pool;
   17446                 :            :         uint8_t reg_id;
   17447                 :            : 
   17448                 :          0 :         aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
   17449                 :          0 :         pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool, mtrs[aso_mtr->offset]);
   17450                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &flow_err);
   17451                 :          0 :         fm->meter_action_y =
   17452                 :          0 :                 mlx5_glue->dv_create_flow_action_aso(priv->sh->rx_domain,
   17453                 :          0 :                                                      pool->devx_obj->obj,
   17454                 :            :                                                      aso_mtr->offset,
   17455                 :            :                                                      (1 << MLX5_FLOW_COLOR_YELLOW),
   17456                 :          0 :                                                      reg_id - REG_C_0);
   17457                 :            : #else
   17458                 :            :         RTE_SET_USED(dev);
   17459                 :            : #endif
   17460         [ #  # ]:          0 :         if (!fm->meter_action_y) {
   17461                 :          0 :                 return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17462                 :            :                                           "Fail to create yellow meter action.");
   17463                 :            :         }
   17464                 :            :         return 0;
   17465                 :            : }
   17466                 :            : 
   17467                 :            : /**
   17468                 :            :  * Create policy action per domain, lock free,
   17469                 :            :  * (mutex should be acquired by caller).
   17470                 :            :  * Dispatcher for action type specific call.
   17471                 :            :  *
   17472                 :            :  * @param[in] dev
   17473                 :            :  *   Pointer to the Ethernet device structure.
   17474                 :            :  * @param[in] mtr_policy
   17475                 :            :  *   Meter policy struct.
   17476                 :            :  * @param[in] action
   17477                 :            :  *   Action specification used to create meter actions.
   17478                 :            :  * @param[in] attr
   17479                 :            :  *   Pointer to the flow attributes.
   17480                 :            :  * @param[out] error
   17481                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17482                 :            :  *   error only.
   17483                 :            :  *
   17484                 :            :  * @return
   17485                 :            :  *   0 on success, otherwise negative errno value.
   17486                 :            :  */
   17487                 :            : static int
   17488                 :          0 : __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev,
   17489                 :            :                         struct mlx5_flow_meter_policy *mtr_policy,
   17490                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
   17491                 :            :                         struct rte_flow_attr *attr,
   17492                 :            :                         enum mlx5_meter_domain domain,
   17493                 :            :                         struct rte_mtr_error *error)
   17494                 :            : {
   17495                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17496                 :            :         struct rte_flow_error flow_err;
   17497                 :            :         const struct rte_flow_action *act;
   17498                 :            :         uint64_t action_flags;
   17499                 :            :         struct mlx5_flow_handle dh;
   17500                 :            :         struct mlx5_flow dev_flow;
   17501                 :            :         struct mlx5_flow_dv_port_id_action_resource port_id_action;
   17502                 :            :         int i, ret;
   17503                 :            :         uint8_t egress, transfer;
   17504                 :            :         struct mlx5_meter_policy_action_container *act_cnt = NULL;
   17505                 :            :         union {
   17506                 :            :                 struct mlx5_flow_dv_modify_hdr_resource res;
   17507                 :            :                 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   17508                 :            :                             sizeof(struct mlx5_modification_cmd) *
   17509                 :            :                             (MLX5_MAX_MODIFY_NUM + 1)];
   17510                 :            :         } mhdr_dummy;
   17511                 :            :         struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
   17512                 :            : 
   17513                 :          0 :         egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   17514         [ #  # ]:          0 :         transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   17515                 :            :         memset(&dh, 0, sizeof(struct mlx5_flow_handle));
   17516                 :            :         memset(&dev_flow, 0, sizeof(struct mlx5_flow));
   17517                 :            :         memset(&port_id_action, 0,
   17518                 :            :                sizeof(struct mlx5_flow_dv_port_id_action_resource));
   17519                 :            :         memset(mhdr_res, 0, sizeof(*mhdr_res));
   17520         [ #  # ]:          0 :         mhdr_res->ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
   17521                 :            :                                        (egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   17522                 :            :                                         MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
   17523                 :          0 :         dev_flow.handle = &dh;
   17524                 :          0 :         dev_flow.dv.port_id_action = &port_id_action;
   17525                 :          0 :         dev_flow.external = true;
   17526         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   17527         [ #  # ]:          0 :                 if (i < MLX5_MTR_RTE_COLORS)
   17528                 :          0 :                         act_cnt = &mtr_policy->act_cnt[i];
   17529                 :            :                 /* Skip the color policy actions creation. */
   17530   [ #  #  #  #  :          0 :                 if ((i == RTE_COLOR_YELLOW && mtr_policy->skip_y) ||
                   #  # ]
   17531         [ #  # ]:          0 :                     (i == RTE_COLOR_GREEN && mtr_policy->skip_g))
   17532                 :          0 :                         continue;
   17533                 :            :                 action_flags = 0;
   17534                 :          0 :                 for (act = actions[i];
   17535   [ #  #  #  # ]:          0 :                      act && act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
   17536   [ #  #  #  #  :          0 :                         switch (act->type) {
          #  #  #  #  #  
                      # ]
   17537                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MARK:
   17538                 :            :                         {
   17539                 :            :                                 uint32_t tag_be = mlx5_flow_mark_set
   17540                 :            :                                         (((const struct rte_flow_action_mark *)
   17541         [ #  # ]:          0 :                                         (act->conf))->id);
   17542                 :            : 
   17543         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17544                 :          0 :                                         return -rte_mtr_error_set(error,
   17545                 :            :                                           ENOTSUP,
   17546                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17547                 :            :                                           NULL,
   17548                 :            :                                           "cannot create policy "
   17549                 :            :                                           "mark action for this color");
   17550         [ #  # ]:          0 :                                 if (flow_dv_tag_resource_register(dev, tag_be,
   17551                 :            :                                                   &dev_flow, &flow_err))
   17552                 :          0 :                                         return -rte_mtr_error_set(error,
   17553                 :            :                                         ENOTSUP,
   17554                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17555                 :            :                                         NULL,
   17556                 :            :                                         "cannot setup policy mark action");
   17557                 :            :                                 MLX5_ASSERT(dev_flow.dv.tag_resource);
   17558                 :          0 :                                 act_cnt->rix_mark =
   17559                 :          0 :                                         dev_flow.handle->dvh.rix_tag;
   17560                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK;
   17561                 :          0 :                                 mtr_policy->mark = 1;
   17562                 :          0 :                                 break;
   17563                 :            :                         }
   17564                 :          0 :                         case RTE_FLOW_ACTION_TYPE_SET_TAG:
   17565         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17566                 :          0 :                                         return -rte_mtr_error_set(error,
   17567                 :            :                                           ENOTSUP,
   17568                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17569                 :            :                                           NULL,
   17570                 :            :                                           "cannot create policy "
   17571                 :            :                                           "set tag action for this color");
   17572         [ #  # ]:          0 :                                 if (flow_dv_convert_action_set_tag
   17573                 :            :                                 (dev, mhdr_res,
   17574                 :            :                                 (const struct rte_flow_action_set_tag *)
   17575                 :          0 :                                 act->conf,  &flow_err))
   17576                 :          0 :                                         return -rte_mtr_error_set(error,
   17577                 :            :                                         ENOTSUP,
   17578                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17579                 :            :                                         NULL, "cannot convert policy "
   17580                 :            :                                         "set tag action");
   17581         [ #  # ]:          0 :                                 if (!mhdr_res->actions_num)
   17582                 :          0 :                                         return -rte_mtr_error_set(error,
   17583                 :            :                                         ENOTSUP,
   17584                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17585                 :            :                                         NULL, "cannot find policy "
   17586                 :            :                                         "set tag action");
   17587                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   17588                 :          0 :                                 break;
   17589                 :          0 :                         case RTE_FLOW_ACTION_TYPE_DROP:
   17590                 :            :                         {
   17591                 :          0 :                                 struct mlx5_flow_mtr_mng *mtrmng =
   17592                 :          0 :                                                 priv->sh->mtrmng;
   17593                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl_data;
   17594                 :            : 
   17595                 :            :                                 /*
   17596                 :            :                                  * Create the drop table with
   17597                 :            :                                  * METER DROP level.
   17598                 :            :                                  */
   17599         [ #  # ]:          0 :                                 if (!mtrmng->drop_tbl[domain]) {
   17600                 :          0 :                                         mtrmng->drop_tbl[domain] =
   17601                 :          0 :                                         flow_dv_tbl_resource_get(dev,
   17602                 :            :                                         MLX5_FLOW_TABLE_LEVEL_METER,
   17603                 :            :                                         egress, transfer, false, NULL, 0,
   17604                 :            :                                         0, MLX5_MTR_TABLE_ID_DROP, &flow_err);
   17605         [ #  # ]:          0 :                                         if (!mtrmng->drop_tbl[domain])
   17606                 :          0 :                                                 return -rte_mtr_error_set
   17607                 :            :                                         (error, ENOTSUP,
   17608                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17609                 :            :                                         NULL,
   17610                 :            :                                         "Failed to create meter drop table");
   17611                 :            :                                 }
   17612                 :          0 :                                 tbl_data = container_of
   17613                 :            :                                 (mtrmng->drop_tbl[domain],
   17614                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17615         [ #  # ]:          0 :                                 if (i < MLX5_MTR_RTE_COLORS) {
   17616                 :          0 :                                         act_cnt->dr_jump_action[domain] =
   17617                 :          0 :                                                 tbl_data->jump.action;
   17618                 :          0 :                                         act_cnt->fate_action =
   17619                 :            :                                                 MLX5_FLOW_FATE_DROP;
   17620                 :            :                                 }
   17621         [ #  # ]:          0 :                                 if (i == RTE_COLOR_RED)
   17622                 :          0 :                                         mtr_policy->dr_drop_action[domain] =
   17623                 :          0 :                                                 tbl_data->jump.action;
   17624                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_DROP;
   17625                 :          0 :                                 break;
   17626                 :            :                         }
   17627                 :          0 :                         case RTE_FLOW_ACTION_TYPE_QUEUE:
   17628                 :            :                         {
   17629         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17630                 :          0 :                                         return -rte_mtr_error_set(error,
   17631                 :            :                                         ENOTSUP,
   17632                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17633                 :            :                                         NULL, "cannot create policy "
   17634                 :            :                                         "fate queue for this color");
   17635                 :          0 :                                 act_cnt->queue =
   17636                 :            :                                 ((const struct rte_flow_action_queue *)
   17637                 :          0 :                                         (act->conf))->index;
   17638                 :          0 :                                 act_cnt->fate_action =
   17639                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   17640                 :          0 :                                 dev_flow.handle->fate_action =
   17641                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   17642                 :          0 :                                 mtr_policy->is_queue = 1;
   17643                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_QUEUE;
   17644                 :          0 :                                 break;
   17645                 :            :                         }
   17646                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RSS:
   17647                 :            :                         {
   17648                 :            :                                 int rss_size;
   17649                 :            : 
   17650         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17651                 :          0 :                                         return -rte_mtr_error_set(error,
   17652                 :            :                                           ENOTSUP,
   17653                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17654                 :            :                                           NULL,
   17655                 :            :                                           "cannot create policy "
   17656                 :            :                                           "rss action for this color");
   17657                 :            :                                 /*
   17658                 :            :                                  * Save RSS conf into policy struct
   17659                 :            :                                  * for translate stage.
   17660                 :            :                                  */
   17661                 :          0 :                                 rss_size = (int)rte_flow_conv
   17662                 :            :                                         (RTE_FLOW_CONV_OP_ACTION,
   17663                 :            :                                         NULL, 0, act, &flow_err);
   17664         [ #  # ]:          0 :                                 if (rss_size <= 0)
   17665                 :          0 :                                         return -rte_mtr_error_set(error,
   17666                 :            :                                           ENOTSUP,
   17667                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17668                 :            :                                           NULL, "Get the wrong "
   17669                 :            :                                           "rss action struct size");
   17670                 :          0 :                                 act_cnt->rss = mlx5_malloc(MLX5_MEM_ZERO,
   17671                 :            :                                                 rss_size, 0, SOCKET_ID_ANY);
   17672         [ #  # ]:          0 :                                 if (!act_cnt->rss)
   17673                 :          0 :                                         return -rte_mtr_error_set(error,
   17674                 :            :                                           ENOTSUP,
   17675                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17676                 :            :                                           NULL,
   17677                 :            :                                           "Fail to malloc rss action memory");
   17678                 :          0 :                                 ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTION,
   17679                 :            :                                         act_cnt->rss, rss_size,
   17680                 :            :                                         act, &flow_err);
   17681         [ #  # ]:          0 :                                 if (ret < 0)
   17682                 :          0 :                                         return -rte_mtr_error_set(error,
   17683                 :            :                                           ENOTSUP,
   17684                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17685                 :            :                                           NULL, "Fail to save "
   17686                 :            :                                           "rss action into policy struct");
   17687                 :          0 :                                 act_cnt->fate_action =
   17688                 :            :                                         MLX5_FLOW_FATE_SHARED_RSS;
   17689                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_RSS;
   17690                 :          0 :                                 break;
   17691                 :            :                         }
   17692                 :          0 :                         case RTE_FLOW_ACTION_TYPE_PORT_ID:
   17693                 :            :                         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   17694                 :            :                         {
   17695                 :            :                                 struct mlx5_flow_dv_port_id_action_resource
   17696                 :            :                                         port_id_resource;
   17697                 :          0 :                                 uint32_t port_id = 0;
   17698                 :            : 
   17699         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17700                 :          0 :                                         return -rte_mtr_error_set(error,
   17701                 :            :                                         ENOTSUP,
   17702                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17703                 :            :                                         NULL, "cannot create policy "
   17704                 :            :                                         "port action for this color");
   17705                 :            :                                 memset(&port_id_resource, 0,
   17706                 :            :                                         sizeof(port_id_resource));
   17707         [ #  # ]:          0 :                                 if (flow_dv_translate_action_port_id(dev, act,
   17708                 :            :                                                 &port_id, &flow_err))
   17709                 :          0 :                                         return -rte_mtr_error_set(error,
   17710                 :            :                                         ENOTSUP,
   17711                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17712                 :            :                                         NULL, "cannot translate "
   17713                 :            :                                         "policy port action");
   17714                 :          0 :                                 port_id_resource.port_id = port_id;
   17715         [ #  # ]:          0 :                                 if (flow_dv_port_id_action_resource_register
   17716                 :            :                                         (dev, &port_id_resource,
   17717                 :            :                                         &dev_flow, &flow_err))
   17718                 :          0 :                                         return -rte_mtr_error_set(error,
   17719                 :            :                                         ENOTSUP,
   17720                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17721                 :            :                                         NULL, "cannot setup "
   17722                 :            :                                         "policy port action");
   17723                 :          0 :                                 act_cnt->rix_port_id_action =
   17724                 :          0 :                                         dev_flow.handle->rix_port_id_action;
   17725                 :          0 :                                 act_cnt->fate_action =
   17726                 :            :                                         MLX5_FLOW_FATE_PORT_ID;
   17727                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   17728                 :          0 :                                 break;
   17729                 :            :                         }
   17730                 :          0 :                         case RTE_FLOW_ACTION_TYPE_JUMP:
   17731                 :            :                         {
   17732                 :            :                                 uint32_t jump_group = 0;
   17733                 :          0 :                                 uint32_t table = 0;
   17734                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl_data;
   17735                 :          0 :                                 struct flow_grp_info grp_info = {
   17736                 :          0 :                                         .external = !!dev_flow.external,
   17737                 :            :                                         .transfer = !!transfer,
   17738                 :          0 :                                         .fdb_def_rule = !!priv->fdb_def_rule,
   17739                 :            :                                         .std_tbl_fix = 0,
   17740                 :          0 :                                         .skip_scale = dev_flow.skip_scale &
   17741                 :            :                                         (1 << MLX5_SCALE_FLOW_GROUP_BIT),
   17742                 :            :                                 };
   17743                 :          0 :                                 struct mlx5_flow_meter_sub_policy *sub_policy =
   17744                 :          0 :                                         mtr_policy->sub_policys[domain][0];
   17745                 :            : 
   17746         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17747                 :          0 :                                         return -rte_mtr_error_set(error,
   17748                 :            :                                           ENOTSUP,
   17749                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17750                 :            :                                           NULL,
   17751                 :            :                                           "cannot create policy "
   17752                 :            :                                           "jump action for this color");
   17753                 :          0 :                                 jump_group =
   17754                 :            :                                 ((const struct rte_flow_action_jump *)
   17755                 :          0 :                                                         act->conf)->group;
   17756         [ #  # ]:          0 :                                 if (mlx5_flow_group_to_table(dev, NULL,
   17757                 :            :                                                        jump_group,
   17758                 :            :                                                        &table,
   17759                 :            :                                                        &grp_info, &flow_err))
   17760                 :          0 :                                         return -rte_mtr_error_set(error,
   17761                 :            :                                         ENOTSUP,
   17762                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17763                 :            :                                         NULL, "cannot setup "
   17764                 :            :                                         "policy jump action");
   17765                 :          0 :                                 sub_policy->jump_tbl[i] =
   17766                 :          0 :                                 flow_dv_tbl_resource_get(dev,
   17767                 :            :                                         table, egress,
   17768                 :            :                                         transfer,
   17769                 :            :                                         !!dev_flow.external,
   17770                 :            :                                         NULL, jump_group, 0,
   17771                 :            :                                         0, &flow_err);
   17772                 :            :                                 if
   17773         [ #  # ]:          0 :                                 (!sub_policy->jump_tbl[i])
   17774                 :          0 :                                         return  -rte_mtr_error_set(error,
   17775                 :            :                                         ENOTSUP,
   17776                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17777                 :            :                                         NULL, "cannot create jump action.");
   17778                 :          0 :                                 tbl_data = container_of
   17779                 :            :                                 (sub_policy->jump_tbl[i],
   17780                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17781                 :          0 :                                 act_cnt->dr_jump_action[domain] =
   17782                 :          0 :                                         tbl_data->jump.action;
   17783                 :          0 :                                 act_cnt->fate_action =
   17784                 :            :                                         MLX5_FLOW_FATE_JUMP;
   17785                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_JUMP;
   17786                 :          0 :                                 break;
   17787                 :            :                         }
   17788                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   17789                 :            :                         {
   17790         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17791                 :          0 :                                         return -rte_mtr_error_set(error,
   17792                 :            :                                           ENOTSUP,
   17793                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17794                 :            :                                           NULL,
   17795                 :            :                                           "cannot create policy modify field for this color");
   17796         [ #  # ]:          0 :                                 if (flow_dv_convert_action_modify_field
   17797                 :            :                                         (dev, mhdr_res, act, attr, &flow_err))
   17798                 :          0 :                                         return -rte_mtr_error_set(error,
   17799                 :            :                                         ENOTSUP,
   17800                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17801                 :            :                                         NULL, "cannot setup policy modify field action");
   17802         [ #  # ]:          0 :                                 if (!mhdr_res->actions_num)
   17803                 :          0 :                                         return -rte_mtr_error_set(error,
   17804                 :            :                                         ENOTSUP,
   17805                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17806                 :            :                                         NULL, "cannot find policy modify field action");
   17807                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   17808                 :          0 :                                 break;
   17809                 :            :                         }
   17810                 :            :                         /*
   17811                 :            :                          * No need to check meter hierarchy for R colors
   17812                 :            :                          * here since it is done in the validation stage.
   17813                 :            :                          */
   17814                 :          0 :                         case RTE_FLOW_ACTION_TYPE_METER:
   17815                 :            :                         {
   17816                 :            :                                 const struct rte_flow_action_meter *mtr;
   17817                 :            :                                 struct mlx5_flow_meter_info *next_fm;
   17818                 :            :                                 struct mlx5_flow_meter_policy *next_policy;
   17819                 :            :                                 struct rte_flow_action tag_action;
   17820                 :            :                                 struct mlx5_rte_flow_action_set_tag set_tag;
   17821                 :          0 :                                 uint32_t next_mtr_idx = 0;
   17822                 :            : 
   17823                 :          0 :                                 mtr = act->conf;
   17824                 :          0 :                                 next_fm = mlx5_flow_meter_find(priv,
   17825                 :          0 :                                                         mtr->mtr_id,
   17826                 :            :                                                         &next_mtr_idx);
   17827         [ #  # ]:          0 :                                 if (!next_fm)
   17828                 :          0 :                                         return -rte_mtr_error_set(error, EINVAL,
   17829                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17830                 :            :                                                 "Fail to find next meter.");
   17831         [ #  # ]:          0 :                                 if (next_fm->def_policy)
   17832                 :          0 :                                         return -rte_mtr_error_set(error, EINVAL,
   17833                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17834                 :            :                                 "Hierarchy only supports termination meter.");
   17835                 :          0 :                                 next_policy = mlx5_flow_meter_policy_find(dev,
   17836                 :            :                                                 next_fm->policy_id, NULL);
   17837                 :            :                                 MLX5_ASSERT(next_policy);
   17838         [ #  # ]:          0 :                                 if (next_fm->drop_cnt) {
   17839                 :          0 :                                         set_tag.id =
   17840                 :          0 :                                                 (enum modify_reg)
   17841                 :          0 :                                                 mlx5_flow_get_reg_id(dev,
   17842                 :            :                                                 MLX5_MTR_ID,
   17843                 :            :                                                 0,
   17844                 :            :                                                 (struct rte_flow_error *)error);
   17845                 :          0 :                                         set_tag.offset = (priv->mtr_reg_share ?
   17846                 :          0 :                                                 MLX5_MTR_COLOR_BITS : 0);
   17847         [ #  # ]:          0 :                                         set_tag.length = (priv->mtr_reg_share ?
   17848                 :            :                                                MLX5_MTR_IDLE_BITS_IN_COLOR_REG :
   17849                 :            :                                                MLX5_REG_BITS);
   17850                 :          0 :                                         set_tag.data = next_mtr_idx;
   17851                 :          0 :                                         tag_action.type =
   17852                 :            :                                                 (enum rte_flow_action_type)
   17853                 :            :                                                 MLX5_RTE_FLOW_ACTION_TYPE_TAG;
   17854                 :          0 :                                         tag_action.conf = &set_tag;
   17855         [ #  # ]:          0 :                                         if (flow_dv_convert_action_set_reg
   17856                 :            :                                                 (mhdr_res, &tag_action,
   17857                 :            :                                                 (struct rte_flow_error *)error))
   17858                 :          0 :                                                 return -rte_errno;
   17859                 :          0 :                                         action_flags |=
   17860                 :            :                                                 MLX5_FLOW_ACTION_SET_TAG;
   17861                 :            :                                 }
   17862   [ #  #  #  # ]:          0 :                                 if (i == RTE_COLOR_YELLOW && next_fm->color_aware &&
   17863         [ #  # ]:          0 :                                     !next_fm->meter_action_y)
   17864         [ #  # ]:          0 :                                         if (__flow_dv_create_mtr_yellow_action(dev, next_fm, error))
   17865                 :          0 :                                                 return -rte_errno;
   17866                 :          0 :                                 act_cnt->fate_action = MLX5_FLOW_FATE_MTR;
   17867                 :          0 :                                 act_cnt->next_mtr_id = next_fm->meter_id;
   17868                 :          0 :                                 act_cnt->next_sub_policy = NULL;
   17869                 :          0 :                                 mtr_policy->is_hierarchy = 1;
   17870         [ #  # ]:          0 :                                 if (next_policy->mark)
   17871                 :          0 :                                         mtr_policy->mark = 1;
   17872                 :          0 :                                 mtr_policy->hierarchy_match_port =
   17873                 :          0 :                                                         next_policy->hierarchy_match_port;
   17874                 :          0 :                                 action_flags |=
   17875                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
   17876                 :          0 :                                 break;
   17877                 :            :                         }
   17878                 :            :                         default:
   17879                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   17880                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17881                 :            :                                           NULL, "action type not supported");
   17882                 :            :                         }
   17883         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) ||
   17884                 :            :                             (action_flags & MLX5_FLOW_ACTION_MODIFY_FIELD)) {
   17885                 :            :                                 /* create modify action if needed. */
   17886                 :          0 :                                 dev_flow.dv.group = 1;
   17887         [ #  # ]:          0 :                                 if (flow_dv_modify_hdr_resource_register
   17888                 :            :                                         (dev, mhdr_res, &dev_flow, &flow_err))
   17889                 :          0 :                                         return -rte_mtr_error_set(error,
   17890                 :            :                                                 ENOTSUP,
   17891                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   17892                 :            :                                                 NULL, "cannot register policy set tag/modify field action");
   17893                 :          0 :                                 act_cnt->modify_hdr =
   17894                 :          0 :                                         dev_flow.handle->dvh.modify_hdr;
   17895                 :            :                         }
   17896                 :            :                 }
   17897                 :            :         }
   17898                 :            :         return 0;
   17899                 :            : }
   17900                 :            : 
   17901                 :            : /**
   17902                 :            :  * Create policy action per domain, lock free,
   17903                 :            :  * (mutex should be acquired by caller).
   17904                 :            :  * Dispatcher for action type specific call.
   17905                 :            :  *
   17906                 :            :  * @param[in] dev
   17907                 :            :  *   Pointer to the Ethernet device structure.
   17908                 :            :  * @param[in] mtr_policy
   17909                 :            :  *   Meter policy struct.
   17910                 :            :  * @param[in] action
   17911                 :            :  *   Action specification used to create meter actions.
   17912                 :            :  * @param[in] attr
   17913                 :            :  *   Pointer to the flow attributes.
   17914                 :            :  * @param[out] error
   17915                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17916                 :            :  *   error only.
   17917                 :            :  *
   17918                 :            :  * @return
   17919                 :            :  *   0 on success, otherwise negative errno value.
   17920                 :            :  */
   17921                 :            : static int
   17922                 :          0 : flow_dv_create_mtr_policy_acts(struct rte_eth_dev *dev,
   17923                 :            :                       struct mlx5_flow_meter_policy *mtr_policy,
   17924                 :            :                       const struct rte_flow_action *actions[RTE_COLORS],
   17925                 :            :                       struct rte_flow_attr *attr,
   17926                 :            :                       struct rte_mtr_error *error)
   17927                 :            : {
   17928                 :            :         int ret, i;
   17929                 :            :         uint16_t sub_policy_num;
   17930                 :            : 
   17931         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   17932                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   17933                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   17934                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   17935         [ #  # ]:          0 :                 if (sub_policy_num) {
   17936                 :          0 :                         ret = __flow_dv_create_domain_policy_acts(dev,
   17937                 :            :                                 mtr_policy, actions, attr,
   17938                 :            :                                 (enum mlx5_meter_domain)i, error);
   17939                 :            :                         /* Cleaning resource is done in the caller level. */
   17940         [ #  # ]:          0 :                         if (ret)
   17941                 :          0 :                                 return ret;
   17942                 :            :                 }
   17943                 :            :         }
   17944                 :            :         return 0;
   17945                 :            : }
   17946                 :            : 
   17947                 :            : /**
   17948                 :            :  * Query a DV flow rule for its statistics via DevX.
   17949                 :            :  *
   17950                 :            :  * @param[in] dev
   17951                 :            :  *   Pointer to Ethernet device.
   17952                 :            :  * @param[in] cnt_idx
   17953                 :            :  *   Index to the flow counter.
   17954                 :            :  * @param[out] data
   17955                 :            :  *   Data retrieved by the query.
   17956                 :            :  * @param[out] error
   17957                 :            :  *   Perform verbose error reporting if not NULL.
   17958                 :            :  *
   17959                 :            :  * @return
   17960                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   17961                 :            :  */
   17962                 :            : static int
   17963                 :          0 : flow_dv_query_count(struct rte_eth_dev *dev, uint32_t cnt_idx, void *data,
   17964                 :            :                     struct rte_flow_error *error)
   17965                 :            : {
   17966                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17967                 :            :         struct rte_flow_query_count *qc = data;
   17968                 :            : 
   17969         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
   17970                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17971                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17972                 :            :                                           NULL,
   17973                 :            :                                           "counters are not supported");
   17974         [ #  # ]:          0 :         if (cnt_idx) {
   17975                 :            :                 uint64_t pkts, bytes;
   17976                 :            :                 struct mlx5_flow_counter *cnt;
   17977                 :          0 :                 int err = _flow_dv_query_count(dev, cnt_idx, &pkts, &bytes);
   17978                 :            : 
   17979         [ #  # ]:          0 :                 if (err)
   17980                 :          0 :                         return rte_flow_error_set(error, -err,
   17981                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17982                 :            :                                         NULL, "cannot read counters");
   17983                 :            :                 cnt = flow_dv_counter_get_by_idx(dev, cnt_idx, NULL);
   17984                 :          0 :                 qc->hits_set = 1;
   17985                 :          0 :                 qc->bytes_set = 1;
   17986                 :          0 :                 qc->hits = pkts - cnt->hits;
   17987                 :          0 :                 qc->bytes = bytes - cnt->bytes;
   17988         [ #  # ]:          0 :                 if (qc->reset) {
   17989                 :          0 :                         cnt->hits = pkts;
   17990                 :          0 :                         cnt->bytes = bytes;
   17991                 :            :                 }
   17992                 :          0 :                 return 0;
   17993                 :            :         }
   17994                 :          0 :         return rte_flow_error_set(error, EINVAL,
   17995                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17996                 :            :                                   NULL,
   17997                 :            :                                   "counters are not available");
   17998                 :            : }
   17999                 :            : 
   18000                 :            : int
   18001                 :          0 : flow_dv_action_query(struct rte_eth_dev *dev,
   18002                 :            :                      const struct rte_flow_action_handle *handle, void *data,
   18003                 :            :                      struct rte_flow_error *error)
   18004                 :            : {
   18005                 :            :         struct mlx5_age_param *age_param;
   18006                 :            :         struct rte_flow_query_age *resp;
   18007                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   18008                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   18009                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   18010                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18011                 :            :         struct mlx5_aso_ct_action *ct;
   18012                 :            :         uint16_t owner;
   18013                 :            :         uint32_t dev_idx;
   18014                 :            : 
   18015   [ #  #  #  # ]:          0 :         switch (type) {
   18016                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   18017                 :          0 :                 age_param = &flow_aso_age_get_by_idx(dev, idx)->age_params;
   18018                 :            :                 resp = data;
   18019                 :          0 :                 resp->aged = rte_atomic_load_explicit(&age_param->state,
   18020                 :            :                                               rte_memory_order_relaxed) == AGE_TMOUT ?
   18021                 :          0 :                                                                           1 : 0;
   18022                 :          0 :                 resp->sec_since_last_hit_valid = !resp->aged;
   18023         [ #  # ]:          0 :                 if (resp->sec_since_last_hit_valid)
   18024                 :          0 :                         resp->sec_since_last_hit = rte_atomic_load_explicit
   18025                 :            :                              (&age_param->sec_since_last_hit, rte_memory_order_relaxed);
   18026                 :            :                 return 0;
   18027                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   18028                 :          0 :                 return flow_dv_query_count(dev, idx, data, error);
   18029                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   18030                 :          0 :                 owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(idx);
   18031         [ #  # ]:          0 :                 if (owner != PORT_ID(priv))
   18032                 :          0 :                         return rte_flow_error_set(error, EACCES,
   18033                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18034                 :            :                                         NULL,
   18035                 :            :                                         "CT object owned by another port");
   18036                 :          0 :                 dev_idx = MLX5_INDIRECT_ACT_CT_GET_IDX(idx);
   18037                 :          0 :                 ct = flow_aso_ct_get_by_dev_idx(dev, dev_idx);
   18038                 :            :                 MLX5_ASSERT(ct);
   18039         [ #  # ]:          0 :                 if (!ct->refcnt)
   18040                 :          0 :                         return rte_flow_error_set(error, EFAULT,
   18041                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18042                 :            :                                         NULL,
   18043                 :            :                                         "CT object is inactive");
   18044                 :          0 :                 ((struct rte_flow_action_conntrack *)data)->peer_port =
   18045                 :          0 :                                                         ct->peer;
   18046                 :          0 :                 ((struct rte_flow_action_conntrack *)data)->is_original_dir =
   18047                 :          0 :                                                         ct->is_original;
   18048         [ #  # ]:          0 :                 if (mlx5_aso_ct_query_by_wqe(priv->sh, MLX5_HW_INV_QUEUE, ct,
   18049                 :            :                                         data, NULL, true))
   18050                 :          0 :                         return rte_flow_error_set(error, EIO,
   18051                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18052                 :            :                                         NULL,
   18053                 :            :                                         "Failed to query CT context");
   18054                 :            :                 return 0;
   18055                 :          0 :         default:
   18056                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   18057                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   18058                 :            :                                           "action type query not supported");
   18059                 :            :         }
   18060                 :            : }
   18061                 :            : 
   18062                 :            : /**
   18063                 :            :  * Query a flow rule AGE action for aging information.
   18064                 :            :  *
   18065                 :            :  * @param[in] dev
   18066                 :            :  *   Pointer to Ethernet device.
   18067                 :            :  * @param[in] flow
   18068                 :            :  *   Pointer to the sub flow.
   18069                 :            :  * @param[out] data
   18070                 :            :  *   data retrieved by the query.
   18071                 :            :  * @param[out] error
   18072                 :            :  *   Perform verbose error reporting if not NULL.
   18073                 :            :  *
   18074                 :            :  * @return
   18075                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   18076                 :            :  */
   18077                 :            : static int
   18078                 :          0 : flow_dv_query_age(struct rte_eth_dev *dev, struct rte_flow *flow,
   18079                 :            :                   void *data, struct rte_flow_error *error)
   18080                 :            : {
   18081                 :            :         struct rte_flow_query_age *resp = data;
   18082                 :            :         struct mlx5_age_param *age_param;
   18083                 :            : 
   18084         [ #  # ]:          0 :         if (flow->age) {
   18085                 :            :                 struct mlx5_aso_age_action *act =
   18086                 :          0 :                                      flow_aso_age_get_by_idx(dev, flow->age);
   18087                 :            : 
   18088                 :          0 :                 age_param = &act->age_params;
   18089         [ #  # ]:          0 :         } else if (flow->counter) {
   18090                 :            :                 age_param = flow_dv_counter_idx_get_age(dev, flow->counter);
   18091                 :            : 
   18092         [ #  # ]:          0 :                 if (!age_param || !age_param->timeout)
   18093                 :          0 :                         return rte_flow_error_set
   18094                 :            :                                         (error, EINVAL,
   18095                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18096                 :            :                                          NULL, "cannot read age data");
   18097                 :            :         } else {
   18098                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   18099                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18100                 :            :                                           NULL, "age data not available");
   18101                 :            :         }
   18102                 :          0 :         resp->aged = rte_atomic_load_explicit(&age_param->state, rte_memory_order_relaxed) ==
   18103                 :          0 :                                      AGE_TMOUT ? 1 : 0;
   18104                 :          0 :         resp->sec_since_last_hit_valid = !resp->aged;
   18105         [ #  # ]:          0 :         if (resp->sec_since_last_hit_valid)
   18106                 :          0 :                 resp->sec_since_last_hit = rte_atomic_load_explicit
   18107                 :            :                              (&age_param->sec_since_last_hit, rte_memory_order_relaxed);
   18108                 :            :         return 0;
   18109                 :            : }
   18110                 :            : 
   18111                 :            : /**
   18112                 :            :  * Query a flow.
   18113                 :            :  *
   18114                 :            :  * @see rte_flow_query()
   18115                 :            :  * @see rte_flow_ops
   18116                 :            :  */
   18117                 :            : static int
   18118                 :          0 : flow_dv_query(struct rte_eth_dev *dev,
   18119                 :            :               struct rte_flow *flow __rte_unused,
   18120                 :            :               const struct rte_flow_action *actions __rte_unused,
   18121                 :            :               void *data __rte_unused,
   18122                 :            :               struct rte_flow_error *error __rte_unused)
   18123                 :            : {
   18124                 :            :         int ret = -EINVAL;
   18125                 :            : 
   18126         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
   18127   [ #  #  #  # ]:          0 :                 switch (actions->type) {
   18128                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   18129                 :            :                         break;
   18130                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   18131                 :          0 :                         ret = flow_dv_query_count(dev, flow->counter, data,
   18132                 :            :                                                   error);
   18133                 :          0 :                         break;
   18134                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   18135                 :          0 :                         ret = flow_dv_query_age(dev, flow, data, error);
   18136                 :          0 :                         break;
   18137                 :          0 :                 default:
   18138                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   18139                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   18140                 :            :                                                   actions,
   18141                 :            :                                                   "action not supported");
   18142                 :            :                 }
   18143                 :            :         }
   18144                 :            :         return ret;
   18145                 :            : }
   18146                 :            : 
   18147                 :            : /**
   18148                 :            :  * Destroy the meter table set.
   18149                 :            :  * Lock free, (mutex should be acquired by caller).
   18150                 :            :  *
   18151                 :            :  * @param[in] dev
   18152                 :            :  *   Pointer to Ethernet device.
   18153                 :            :  * @param[in] fm
   18154                 :            :  *   Meter information table.
   18155                 :            :  */
   18156                 :            : static void
   18157                 :          0 : flow_dv_destroy_mtr_tbls(struct rte_eth_dev *dev,
   18158                 :            :                         struct mlx5_flow_meter_info *fm)
   18159                 :            : {
   18160                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18161                 :            :         int i;
   18162                 :            : 
   18163   [ #  #  #  # ]:          0 :         if (!fm || !priv->sh->config.dv_flow_en)
   18164                 :            :                 return;
   18165         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18166         [ #  # ]:          0 :                 if (fm->drop_rule[i]) {
   18167                 :            :                         claim_zero(mlx5_flow_os_destroy_flow(fm->drop_rule[i]));
   18168                 :          0 :                         fm->drop_rule[i] = NULL;
   18169                 :            :                 }
   18170                 :            :         }
   18171                 :            : }
   18172                 :            : 
   18173                 :            : static void
   18174                 :          0 : flow_dv_destroy_mtr_drop_tbls(struct rte_eth_dev *dev)
   18175                 :            : {
   18176                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18177                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18178                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   18179                 :            :         int i, j;
   18180                 :            : 
   18181         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18182         [ #  # ]:          0 :                 if (mtrmng->def_rule[i]) {
   18183                 :            :                         claim_zero(mlx5_flow_os_destroy_flow
   18184                 :            :                                         (mtrmng->def_rule[i]));
   18185                 :          0 :                         mtrmng->def_rule[i] = NULL;
   18186                 :            :                 }
   18187         [ #  # ]:          0 :                 if (mtrmng->def_matcher[i]) {
   18188                 :          0 :                         tbl = container_of(mtrmng->def_matcher[i]->tbl,
   18189                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   18190                 :          0 :                         mlx5_list_unregister(tbl->matchers,
   18191                 :            :                                              &mtrmng->def_matcher[i]->entry);
   18192                 :          0 :                         mtrmng->def_matcher[i] = NULL;
   18193                 :            :                 }
   18194         [ #  # ]:          0 :                 for (j = 0; j < MLX5_REG_BITS; j++) {
   18195         [ #  # ]:          0 :                         if (mtrmng->drop_matcher[i][j]) {
   18196                 :            :                                 tbl =
   18197                 :          0 :                                 container_of(mtrmng->drop_matcher[i][j]->tbl,
   18198                 :            :                                              struct mlx5_flow_tbl_data_entry,
   18199                 :            :                                              tbl);
   18200                 :          0 :                                 mlx5_list_unregister(tbl->matchers,
   18201                 :            :                                             &mtrmng->drop_matcher[i][j]->entry);
   18202                 :          0 :                                 mtrmng->drop_matcher[i][j] = NULL;
   18203                 :            :                         }
   18204                 :            :                 }
   18205         [ #  # ]:          0 :                 if (mtrmng->drop_tbl[i]) {
   18206                 :          0 :                         flow_dv_tbl_resource_release(MLX5_SH(dev),
   18207                 :            :                                 mtrmng->drop_tbl[i]);
   18208                 :          0 :                         mtrmng->drop_tbl[i] = NULL;
   18209                 :            :                 }
   18210                 :            :         }
   18211                 :          0 : }
   18212                 :            : 
   18213                 :            : /* Number of meter flow actions, count and jump or count and drop. */
   18214                 :            : #define METER_ACTIONS 2
   18215                 :            : 
   18216                 :            : static void
   18217                 :          0 : __flow_dv_destroy_domain_def_policy(struct rte_eth_dev *dev,
   18218                 :            :                                     enum mlx5_meter_domain domain)
   18219                 :            : {
   18220                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18221                 :          0 :         struct mlx5_flow_meter_def_policy *def_policy =
   18222                 :          0 :                         priv->sh->mtrmng->def_policy[domain];
   18223                 :            : 
   18224                 :          0 :         __flow_dv_destroy_sub_policy_rules(dev, &def_policy->sub_policy);
   18225                 :          0 :         mlx5_free(def_policy);
   18226                 :          0 :         priv->sh->mtrmng->def_policy[domain] = NULL;
   18227                 :          0 : }
   18228                 :            : 
   18229                 :            : /**
   18230                 :            :  * Destroy the default policy table set.
   18231                 :            :  *
   18232                 :            :  * @param[in] dev
   18233                 :            :  *   Pointer to Ethernet device.
   18234                 :            :  */
   18235                 :            : static void
   18236                 :          0 : flow_dv_destroy_def_policy(struct rte_eth_dev *dev)
   18237                 :            : {
   18238                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18239                 :            :         int i;
   18240                 :            : 
   18241         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++)
   18242         [ #  # ]:          0 :                 if (priv->sh->mtrmng->def_policy[i])
   18243                 :          0 :                         __flow_dv_destroy_domain_def_policy(dev,
   18244                 :            :                                         (enum mlx5_meter_domain)i);
   18245                 :          0 :         priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
   18246                 :          0 : }
   18247                 :            : 
   18248                 :            : static int
   18249                 :          0 : __flow_dv_create_policy_flow(struct rte_eth_dev *dev,
   18250                 :            :                         uint32_t color_reg_c_idx,
   18251                 :            :                         enum rte_color color, struct mlx5_flow_dv_matcher *matcher,
   18252                 :            :                         int actions_n, void *actions,
   18253                 :            :                         bool match_src_port, const struct rte_flow_item *item,
   18254                 :            :                         void **rule, const struct rte_flow_attr *attr)
   18255                 :            : {
   18256                 :            :         int ret;
   18257                 :          0 :         struct mlx5_flow_dv_match_params value = {
   18258                 :            :                 .size = sizeof(value.buf),
   18259                 :            :         };
   18260                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18261                 :            :         uint8_t misc_mask;
   18262                 :            : 
   18263   [ #  #  #  # ]:          0 :         if (match_src_port && priv->sh->esw_mode) {
   18264   [ #  #  #  # ]:          0 :                 if (item && item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT)
   18265                 :          0 :                         ret = flow_dv_translate_item_represented_port(dev, value.buf,
   18266                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_V);
   18267   [ #  #  #  # ]:          0 :                 else if (item && item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
   18268                 :          0 :                         ret = flow_dv_translate_item_port_representor(dev, value.buf,
   18269                 :            :                                                                       MLX5_SET_MATCHER_SW_V);
   18270                 :            :                 else
   18271                 :          0 :                         ret = flow_dv_translate_item_port_id(dev, value.buf,
   18272                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_V);
   18273         [ #  # ]:          0 :                 if (ret) {
   18274                 :          0 :                         DRV_LOG(ERR, "Failed to create meter policy%d flow's"
   18275                 :            :                                 " value with port.", color);
   18276                 :          0 :                         return -1;
   18277                 :            :                 }
   18278                 :            :         }
   18279                 :          0 :         flow_dv_match_meta_reg(value.buf, (enum modify_reg)color_reg_c_idx,
   18280                 :            :                                rte_col_2_mlx5_col(color), UINT32_MAX);
   18281         [ #  # ]:          0 :         misc_mask = flow_dv_matcher_enable(matcher->mask.buf);
   18282                 :            :         __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18283                 :          0 :         ret = mlx5_flow_os_create_flow(matcher->matcher_object, (void *)&value,
   18284                 :            :                                        actions_n, actions, rule);
   18285                 :            :         if (ret) {
   18286                 :          0 :                 DRV_LOG(ERR, "Failed to create meter policy%d flow.", color);
   18287                 :          0 :                 return -1;
   18288                 :            :         }
   18289                 :            :         return 0;
   18290                 :            : }
   18291                 :            : 
   18292                 :            : static int
   18293                 :          0 : __flow_dv_create_policy_matcher(struct rte_eth_dev *dev,
   18294                 :            :                         uint32_t color_reg_c_idx,
   18295                 :            :                         uint16_t priority,
   18296                 :            :                         struct mlx5_flow_meter_sub_policy *sub_policy,
   18297                 :            :                         const struct rte_flow_attr *attr,
   18298                 :            :                         bool match_src_port,
   18299                 :            :                         const struct rte_flow_item *item,
   18300                 :            :                         struct mlx5_flow_dv_matcher **policy_matcher,
   18301                 :            :                         struct rte_flow_error *error)
   18302                 :            : {
   18303                 :            :         struct mlx5_list_entry *entry;
   18304                 :          0 :         struct mlx5_flow_tbl_resource *tbl_rsc = sub_policy->tbl_rsc;
   18305                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   18306                 :            :                 .mask = {
   18307                 :            :                         .size = sizeof(matcher.mask.buf),
   18308                 :            :                 },
   18309                 :            :                 .tbl = tbl_rsc,
   18310                 :            :         };
   18311                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   18312                 :            :                 .error = error,
   18313                 :            :                 .data = &matcher,
   18314                 :            :         };
   18315                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18316                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18317                 :            :         const uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
   18318                 :            :         int ret;
   18319                 :            : 
   18320   [ #  #  #  # ]:          0 :         if (match_src_port && priv->sh->esw_mode) {
   18321   [ #  #  #  # ]:          0 :                 if (item && item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT)
   18322                 :          0 :                         ret = flow_dv_translate_item_represented_port(dev, matcher.mask.buf,
   18323                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_M);
   18324   [ #  #  #  # ]:          0 :                 else if (item && item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
   18325                 :          0 :                         ret = flow_dv_translate_item_port_representor(dev, matcher.mask.buf,
   18326                 :            :                                                                       MLX5_SET_MATCHER_SW_M);
   18327                 :            :                 else
   18328                 :          0 :                         ret = flow_dv_translate_item_port_id(dev, matcher.mask.buf,
   18329                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_M);
   18330         [ #  # ]:          0 :                 if (ret) {
   18331                 :          0 :                         DRV_LOG(ERR, "Failed to register meter policy%d matcher"
   18332                 :            :                                 " with port.", priority);
   18333                 :          0 :                         return -1;
   18334                 :            :                 }
   18335                 :            :         }
   18336                 :          0 :         tbl_data = container_of(tbl_rsc, struct mlx5_flow_tbl_data_entry, tbl);
   18337                 :          0 :         flow_dv_match_meta_reg(matcher.mask.buf,
   18338                 :            :                 (enum modify_reg)color_reg_c_idx, color_mask, color_mask);
   18339                 :          0 :         matcher.priority = priority;
   18340                 :          0 :         matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
   18341                 :            :                                     matcher.mask.size);
   18342                 :          0 :         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18343         [ #  # ]:          0 :         if (!entry) {
   18344                 :          0 :                 DRV_LOG(ERR, "Failed to register meter drop matcher.");
   18345                 :          0 :                 return -1;
   18346                 :            :         }
   18347                 :          0 :         *policy_matcher =
   18348                 :            :                 container_of(entry, struct mlx5_flow_dv_matcher, entry);
   18349                 :          0 :         return 0;
   18350                 :            : }
   18351                 :            : 
   18352                 :            : /**
   18353                 :            :  * Create the policy rules per domain.
   18354                 :            :  *
   18355                 :            :  * @param[in] dev
   18356                 :            :  *   Pointer to Ethernet device.
   18357                 :            :  * @param[in] sub_policy
   18358                 :            :  *    Pointer to sub policy table..
   18359                 :            :  * @param[in] egress
   18360                 :            :  *   Direction of the table.
   18361                 :            :  * @param[in] transfer
   18362                 :            :  *   E-Switch or NIC flow.
   18363                 :            :  * @param[in] acts
   18364                 :            :  *   Pointer to policy action list per color.
   18365                 :            :  *
   18366                 :            :  * @return
   18367                 :            :  *   0 on success, -1 otherwise.
   18368                 :            :  */
   18369                 :            : static int
   18370                 :          0 : __flow_dv_create_domain_policy_rules(struct rte_eth_dev *dev,
   18371                 :            :                 struct mlx5_flow_meter_sub_policy *sub_policy,
   18372                 :            :                 uint8_t egress, uint8_t transfer, bool *match_src_port,
   18373                 :            :                 struct mlx5_meter_policy_acts acts[RTE_COLORS])
   18374                 :            : {
   18375                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18376                 :            :         struct rte_flow_error flow_err;
   18377                 :            :         uint32_t color_reg_c_idx;
   18378                 :          0 :         struct rte_flow_attr attr = {
   18379                 :            :                 .group = MLX5_FLOW_TABLE_LEVEL_POLICY,
   18380                 :            :                 .priority = 0,
   18381                 :            :                 .ingress = 0,
   18382                 :          0 :                 .egress = !!egress,
   18383                 :          0 :                 .transfer = !!transfer,
   18384                 :            :                 .reserved = 0,
   18385                 :            :         };
   18386                 :            :         int i;
   18387                 :            :         uint16_t priority;
   18388                 :          0 :         int ret = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &flow_err);
   18389                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   18390                 :          0 :         struct mlx5_sub_policy_color_rule *tmp_rules[RTE_COLORS] = {NULL};
   18391                 :            : 
   18392         [ #  # ]:          0 :         if (ret < 0)
   18393                 :            :                 return -1;
   18394                 :            :         /* Create policy table with POLICY level. */
   18395         [ #  # ]:          0 :         if (!sub_policy->tbl_rsc)
   18396                 :          0 :                 sub_policy->tbl_rsc = flow_dv_tbl_resource_get(dev,
   18397                 :            :                                 MLX5_FLOW_TABLE_LEVEL_POLICY,
   18398                 :            :                                 egress, transfer, false, NULL, 0, 0,
   18399                 :          0 :                                 sub_policy->idx, &flow_err);
   18400         [ #  # ]:          0 :         if (!sub_policy->tbl_rsc) {
   18401                 :          0 :                 DRV_LOG(ERR,
   18402                 :            :                         "Failed to create meter sub policy table.");
   18403                 :          0 :                 return -1;
   18404                 :            :         }
   18405                 :            :         /* Prepare matchers. */
   18406                 :          0 :         color_reg_c_idx = ret;
   18407         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   18408                 :          0 :                 TAILQ_INIT(&sub_policy->color_rules[i]);
   18409         [ #  # ]:          0 :                 if (!acts[i].actions_n)
   18410                 :          0 :                         continue;
   18411                 :          0 :                 color_rule = mlx5_malloc(MLX5_MEM_ZERO,
   18412                 :            :                                 sizeof(struct mlx5_sub_policy_color_rule),
   18413                 :            :                                 0, SOCKET_ID_ANY);
   18414         [ #  # ]:          0 :                 if (!color_rule) {
   18415                 :          0 :                         DRV_LOG(ERR, "No memory to create color rule.");
   18416                 :          0 :                         goto err_exit;
   18417                 :            :                 }
   18418                 :          0 :                 tmp_rules[i] = color_rule;
   18419                 :          0 :                 TAILQ_INSERT_TAIL(&sub_policy->color_rules[i],
   18420                 :            :                                   color_rule, next_port);
   18421                 :          0 :                 color_rule->src_port = priv->representor_id;
   18422                 :          0 :                 priority = (match_src_port[i] == match_src_port[RTE_COLOR_GREEN]) ?
   18423                 :          0 :                            MLX5_MTR_POLICY_MATCHER_PRIO : (MLX5_MTR_POLICY_MATCHER_PRIO + 1);
   18424                 :            :                 /* Create matchers for colors. */
   18425         [ #  # ]:          0 :                 if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
   18426                 :            :                                 priority, sub_policy,
   18427                 :            :                                 &attr, match_src_port[i], NULL,
   18428                 :            :                                 &color_rule->matcher, &flow_err)) {
   18429                 :          0 :                         DRV_LOG(ERR, "Failed to create color%u matcher.", i);
   18430                 :          0 :                         goto err_exit;
   18431                 :            :                 }
   18432                 :            :                 /* Create flow, matching color. */
   18433         [ #  # ]:          0 :                 if (__flow_dv_create_policy_flow(dev,
   18434                 :            :                                 color_reg_c_idx, (enum rte_color)i,
   18435                 :            :                                 color_rule->matcher,
   18436                 :          0 :                                 acts[i].actions_n, acts[i].dv_actions,
   18437                 :          0 :                                 match_src_port[i], NULL, &color_rule->rule,
   18438                 :            :                                 &attr)) {
   18439                 :          0 :                         DRV_LOG(ERR, "Failed to create color%u rule.", i);
   18440                 :          0 :                         goto err_exit;
   18441                 :            :                 }
   18442                 :            :         }
   18443                 :            :         return 0;
   18444                 :            : err_exit:
   18445                 :            :         /* All the policy rules will be cleared. */
   18446                 :            :         do {
   18447                 :          0 :                 color_rule = tmp_rules[i];
   18448         [ #  # ]:          0 :                 if (color_rule) {
   18449         [ #  # ]:          0 :                         if (color_rule->rule)
   18450                 :            :                                 mlx5_flow_os_destroy_flow(color_rule->rule);
   18451         [ #  # ]:          0 :                         if (color_rule->matcher) {
   18452                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl =
   18453                 :          0 :                                         container_of(color_rule->matcher->tbl,
   18454                 :            :                                                      typeof(*tbl), tbl);
   18455                 :          0 :                                 mlx5_list_unregister(tbl->matchers,
   18456                 :            :                                                 &color_rule->matcher->entry);
   18457                 :            :                         }
   18458         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[i],
   18459                 :            :                                      color_rule, next_port);
   18460                 :          0 :                         mlx5_free(color_rule);
   18461                 :            :                 }
   18462         [ #  # ]:          0 :         } while (i--);
   18463                 :            :         return -1;
   18464                 :            : }
   18465                 :            : 
   18466                 :            : static int
   18467                 :          0 : __flow_dv_create_policy_acts_rules(struct rte_eth_dev *dev,
   18468                 :            :                         struct mlx5_flow_meter_policy *mtr_policy,
   18469                 :            :                         struct mlx5_flow_meter_sub_policy *sub_policy,
   18470                 :            :                         uint32_t domain)
   18471                 :            : {
   18472                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18473                 :            :         struct mlx5_meter_policy_acts acts[RTE_COLORS];
   18474                 :            :         struct mlx5_flow_dv_tag_resource *tag;
   18475                 :            :         struct mlx5_flow_dv_port_id_action_resource *port_action;
   18476                 :            :         struct mlx5_hrxq *hrxq;
   18477                 :          0 :         struct mlx5_flow_meter_info *next_fm[RTE_COLORS] = {NULL};
   18478                 :            :         struct mlx5_flow_meter_policy *next_policy;
   18479                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy;
   18480                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18481                 :            :         struct rte_flow_error error;
   18482                 :          0 :         uint8_t egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18483                 :          0 :         uint8_t transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18484   [ #  #  #  #  :          0 :         bool mtr_first = egress || (transfer && priv->representor_id != UINT16_MAX);
                   #  # ]
   18485                 :          0 :         bool match_src_port[RTE_COLORS] = {false};
   18486                 :            :         int i;
   18487                 :            : 
   18488                 :            :         /* If RSS or Queue, no previous actions / rules is created. */
   18489         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   18490                 :          0 :                 acts[i].actions_n = 0;
   18491         [ #  # ]:          0 :                 if (i == RTE_COLOR_RED) {
   18492                 :            :                         /* Only support drop on red. */
   18493                 :          0 :                         acts[i].dv_actions[0] =
   18494                 :          0 :                                 mtr_policy->dr_drop_action[domain];
   18495                 :          0 :                         acts[i].actions_n = 1;
   18496                 :          0 :                         continue;
   18497                 :            :                 }
   18498         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR) {
   18499                 :          0 :                         struct rte_flow_attr attr = {
   18500                 :            :                                 .transfer = transfer
   18501                 :            :                         };
   18502                 :            : 
   18503                 :          0 :                         next_fm[i] = mlx5_flow_meter_find(priv,
   18504                 :            :                                         mtr_policy->act_cnt[i].next_mtr_id,
   18505                 :            :                                         NULL);
   18506         [ #  # ]:          0 :                         if (!next_fm[i]) {
   18507                 :          0 :                                 DRV_LOG(ERR,
   18508                 :            :                                         "Failed to get next hierarchy meter.");
   18509                 :          0 :                                 goto err_exit;
   18510                 :            :                         }
   18511         [ #  # ]:          0 :                         if (mlx5_flow_meter_attach(priv, next_fm[i],
   18512                 :            :                                                    &attr, &error)) {
   18513                 :          0 :                                 DRV_LOG(ERR, "%s", error.message);
   18514                 :          0 :                                 next_fm[i] = NULL;
   18515                 :          0 :                                 goto err_exit;
   18516                 :            :                         }
   18517                 :            :                         /* Meter action must be the first for TX. */
   18518         [ #  # ]:          0 :                         if (mtr_first) {
   18519                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18520         [ #  # ]:          0 :                                         (next_fm[i]->color_aware && i == RTE_COLOR_YELLOW) ?
   18521         [ #  # ]:          0 :                                                 next_fm[i]->meter_action_y :
   18522                 :            :                                                 next_fm[i]->meter_action_g;
   18523                 :          0 :                                 acts[i].actions_n++;
   18524                 :            :                         }
   18525                 :            :                 }
   18526         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].rix_mark) {
   18527                 :          0 :                         tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG],
   18528                 :            :                                         mtr_policy->act_cnt[i].rix_mark);
   18529         [ #  # ]:          0 :                         if (!tag) {
   18530                 :          0 :                                 DRV_LOG(ERR, "Failed to find "
   18531                 :            :                                 "mark action for policy.");
   18532                 :          0 :                                 goto err_exit;
   18533                 :            :                         }
   18534                 :          0 :                         acts[i].dv_actions[acts[i].actions_n] = tag->action;
   18535                 :          0 :                         acts[i].actions_n++;
   18536                 :            :                 }
   18537         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].modify_hdr) {
   18538                 :          0 :                         acts[i].dv_actions[acts[i].actions_n] =
   18539                 :          0 :                                 mtr_policy->act_cnt[i].modify_hdr->action;
   18540                 :          0 :                         acts[i].actions_n++;
   18541                 :            :                 }
   18542         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action) {
   18543   [ #  #  #  #  :          0 :                         switch (mtr_policy->act_cnt[i].fate_action) {
                      # ]
   18544                 :          0 :                         case MLX5_FLOW_FATE_PORT_ID:
   18545                 :          0 :                                 port_action = mlx5_ipool_get
   18546                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_PORT_ID],
   18547                 :            :                                 mtr_policy->act_cnt[i].rix_port_id_action);
   18548         [ #  # ]:          0 :                                 if (!port_action) {
   18549                 :          0 :                                         DRV_LOG(ERR, "Failed to find "
   18550                 :            :                                                 "port action for policy.");
   18551                 :          0 :                                         goto err_exit;
   18552                 :            :                                 }
   18553                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18554                 :          0 :                                         port_action->action;
   18555                 :          0 :                                 acts[i].actions_n++;
   18556                 :          0 :                                 match_src_port[i] = true;
   18557                 :          0 :                                 break;
   18558                 :          0 :                         case MLX5_FLOW_FATE_DROP:
   18559                 :            :                         case MLX5_FLOW_FATE_JUMP:
   18560                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18561                 :          0 :                                 mtr_policy->act_cnt[i].dr_jump_action[domain];
   18562                 :          0 :                                 acts[i].actions_n++;
   18563                 :          0 :                                 break;
   18564                 :          0 :                         case MLX5_FLOW_FATE_SHARED_RSS:
   18565                 :            :                         case MLX5_FLOW_FATE_QUEUE:
   18566                 :          0 :                                 hrxq = mlx5_ipool_get
   18567                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_HRXQ],
   18568                 :            :                                          sub_policy->rix_hrxq[i]);
   18569         [ #  # ]:          0 :                                 if (!hrxq) {
   18570                 :          0 :                                         DRV_LOG(ERR, "Failed to find "
   18571                 :            :                                                 "queue action for policy.");
   18572                 :          0 :                                         goto err_exit;
   18573                 :            :                                 }
   18574                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18575                 :          0 :                                         hrxq->action;
   18576                 :          0 :                                 acts[i].actions_n++;
   18577                 :          0 :                                 break;
   18578                 :          0 :                         case MLX5_FLOW_FATE_MTR:
   18579         [ #  # ]:          0 :                                 if (!next_fm[i]) {
   18580                 :          0 :                                         DRV_LOG(ERR,
   18581                 :            :                                                 "No next hierarchy meter.");
   18582                 :          0 :                                         goto err_exit;
   18583                 :            :                                 }
   18584         [ #  # ]:          0 :                                 if (!mtr_first) {
   18585                 :          0 :                                         acts[i].dv_actions[acts[i].actions_n] =
   18586         [ #  # ]:          0 :                                                 (next_fm[i]->color_aware && i == RTE_COLOR_YELLOW) ?
   18587         [ #  # ]:          0 :                                                         next_fm[i]->meter_action_y :
   18588                 :            :                                                         next_fm[i]->meter_action_g;
   18589                 :          0 :                                         acts[i].actions_n++;
   18590                 :            :                                 }
   18591         [ #  # ]:          0 :                                 if (mtr_policy->act_cnt[i].next_sub_policy) {
   18592                 :            :                                         next_sub_policy =
   18593                 :            :                                         mtr_policy->act_cnt[i].next_sub_policy;
   18594                 :            :                                 } else {
   18595                 :            :                                         next_policy =
   18596                 :          0 :                                                 mlx5_flow_meter_policy_find(dev,
   18597                 :            :                                                                 next_fm[i]->policy_id, NULL);
   18598                 :            :                                         MLX5_ASSERT(next_policy);
   18599                 :          0 :                                         next_sub_policy =
   18600                 :          0 :                                         next_policy->sub_policys[domain][0];
   18601                 :            :                                 }
   18602                 :            :                                 tbl_data =
   18603                 :          0 :                                         container_of(next_sub_policy->tbl_rsc,
   18604                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18605                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n++] =
   18606                 :          0 :                                                         tbl_data->jump.action;
   18607         [ #  # ]:          0 :                                 if (mtr_policy->act_cnt[i].modify_hdr)
   18608                 :          0 :                                         match_src_port[i] = !!transfer;
   18609                 :            :                                 break;
   18610                 :            :                         default:
   18611                 :            :                                 /*Queue action do nothing*/
   18612                 :            :                                 break;
   18613                 :            :                         }
   18614                 :            :                 }
   18615                 :            :         }
   18616         [ #  # ]:          0 :         if (__flow_dv_create_domain_policy_rules(dev, sub_policy,
   18617                 :            :                                 egress, transfer, match_src_port, acts)) {
   18618                 :          0 :                 DRV_LOG(ERR,
   18619                 :            :                         "Failed to create policy rules per domain.");
   18620                 :          0 :                 goto err_exit;
   18621                 :            :         }
   18622   [ #  #  #  # ]:          0 :         if (match_src_port[RTE_COLOR_GREEN] || match_src_port[RTE_COLOR_YELLOW]) {
   18623                 :          0 :                 mtr_policy->match_port = 1;
   18624                 :          0 :                 mtr_policy->hierarchy_match_port = 1;
   18625                 :            :         }
   18626                 :            :         return 0;
   18627                 :            : err_exit:
   18628         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++)
   18629         [ #  # ]:          0 :                 if (next_fm[i])
   18630                 :          0 :                         mlx5_flow_meter_detach(priv, next_fm[i]);
   18631                 :            :         return -1;
   18632                 :            : }
   18633                 :            : 
   18634                 :            : /**
   18635                 :            :  * Create the policy rules.
   18636                 :            :  *
   18637                 :            :  * @param[in] dev
   18638                 :            :  *   Pointer to Ethernet device.
   18639                 :            :  * @param[in,out] mtr_policy
   18640                 :            :  *   Pointer to meter policy table.
   18641                 :            :  *
   18642                 :            :  * @return
   18643                 :            :  *   0 on success, -1 otherwise.
   18644                 :            :  */
   18645                 :            : static int
   18646                 :          0 : flow_dv_create_policy_rules(struct rte_eth_dev *dev,
   18647                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
   18648                 :            : {
   18649                 :            :         int i;
   18650                 :            :         int ret = 0;
   18651                 :            :         uint16_t sub_policy_num;
   18652                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_push_thread_workspace();
   18653                 :            : 
   18654                 :            :         RTE_SET_USED(wks);
   18655         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18656                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   18657                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   18658                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18659         [ #  # ]:          0 :                 if (!sub_policy_num)
   18660                 :          0 :                         continue;
   18661                 :            :                 /* Prepare actions list and create policy rules. */
   18662         [ #  # ]:          0 :                 if (__flow_dv_create_policy_acts_rules(dev, mtr_policy,
   18663                 :          0 :                         mtr_policy->sub_policys[i][0], i)) {
   18664                 :          0 :                         DRV_LOG(ERR, "Failed to create policy action "
   18665                 :            :                                 "list per domain.");
   18666                 :            :                         ret = -1;
   18667                 :          0 :                         goto exit;
   18668                 :            :                 }
   18669                 :            :         }
   18670                 :          0 : exit:
   18671                 :          0 :         mlx5_flow_pop_thread_workspace();
   18672                 :          0 :         return ret;
   18673                 :            : }
   18674                 :            : 
   18675                 :            : static int
   18676                 :          0 : __flow_dv_create_domain_def_policy(struct rte_eth_dev *dev, uint32_t domain)
   18677                 :            : {
   18678                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18679                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18680                 :            :         struct mlx5_flow_meter_def_policy *def_policy;
   18681                 :            :         struct mlx5_flow_tbl_resource *jump_tbl;
   18682                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18683                 :            :         uint8_t egress, transfer;
   18684                 :            :         struct rte_flow_error error;
   18685                 :            :         struct mlx5_meter_policy_acts acts[RTE_COLORS];
   18686                 :          0 :         bool match_src_port[RTE_COLORS] = {false};
   18687                 :            :         int ret;
   18688                 :            : 
   18689                 :          0 :         egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18690                 :          0 :         transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18691                 :          0 :         def_policy = mtrmng->def_policy[domain];
   18692         [ #  # ]:          0 :         if (!def_policy) {
   18693                 :          0 :                 def_policy = mlx5_malloc(MLX5_MEM_ZERO,
   18694                 :            :                         sizeof(struct mlx5_flow_meter_def_policy),
   18695                 :            :                         RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
   18696         [ #  # ]:          0 :                 if (!def_policy) {
   18697                 :          0 :                         DRV_LOG(ERR, "Failed to alloc default policy table.");
   18698                 :          0 :                         goto def_policy_error;
   18699                 :            :                 }
   18700                 :          0 :                 mtrmng->def_policy[domain] = def_policy;
   18701                 :            :                 /* Create the meter suffix table with SUFFIX level. */
   18702                 :          0 :                 jump_tbl = flow_dv_tbl_resource_get(dev,
   18703                 :            :                                 MLX5_FLOW_TABLE_LEVEL_METER,
   18704                 :            :                                 egress, transfer, false, NULL, 0,
   18705                 :            :                                 0, MLX5_MTR_TABLE_ID_SUFFIX, &error);
   18706         [ #  # ]:          0 :                 if (!jump_tbl) {
   18707                 :          0 :                         DRV_LOG(ERR,
   18708                 :            :                                 "Failed to create meter suffix table.");
   18709                 :          0 :                         goto def_policy_error;
   18710                 :            :                 }
   18711                 :          0 :                 def_policy->sub_policy.jump_tbl[RTE_COLOR_GREEN] = jump_tbl;
   18712                 :          0 :                 tbl_data = container_of(jump_tbl,
   18713                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18714                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_GREEN] =
   18715                 :          0 :                                                 tbl_data->jump.action;
   18716                 :          0 :                 acts[RTE_COLOR_GREEN].dv_actions[0] = tbl_data->jump.action;
   18717                 :          0 :                 acts[RTE_COLOR_GREEN].actions_n = 1;
   18718                 :            :                 /*
   18719                 :            :                  * YELLOW has the same default policy as GREEN does.
   18720                 :            :                  * G & Y share the same table and action. The 2nd time of table
   18721                 :            :                  * resource getting is just to update the reference count for
   18722                 :            :                  * the releasing stage.
   18723                 :            :                  */
   18724                 :          0 :                 jump_tbl = flow_dv_tbl_resource_get(dev,
   18725                 :            :                                 MLX5_FLOW_TABLE_LEVEL_METER,
   18726                 :            :                                 egress, transfer, false, NULL, 0,
   18727                 :            :                                 0, MLX5_MTR_TABLE_ID_SUFFIX, &error);
   18728         [ #  # ]:          0 :                 if (!jump_tbl) {
   18729                 :          0 :                         DRV_LOG(ERR,
   18730                 :            :                                 "Failed to get meter suffix table.");
   18731                 :          0 :                         goto def_policy_error;
   18732                 :            :                 }
   18733                 :          0 :                 def_policy->sub_policy.jump_tbl[RTE_COLOR_YELLOW] = jump_tbl;
   18734                 :          0 :                 tbl_data = container_of(jump_tbl,
   18735                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18736                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_YELLOW] =
   18737                 :          0 :                                                 tbl_data->jump.action;
   18738                 :          0 :                 acts[RTE_COLOR_YELLOW].dv_actions[0] = tbl_data->jump.action;
   18739                 :          0 :                 acts[RTE_COLOR_YELLOW].actions_n = 1;
   18740                 :            :                 /* Create jump action to the drop table. */
   18741         [ #  # ]:          0 :                 if (!mtrmng->drop_tbl[domain]) {
   18742                 :          0 :                         mtrmng->drop_tbl[domain] = flow_dv_tbl_resource_get
   18743                 :            :                                 (dev, MLX5_FLOW_TABLE_LEVEL_METER,
   18744                 :            :                                  egress, transfer, false, NULL, 0,
   18745                 :            :                                  0, MLX5_MTR_TABLE_ID_DROP, &error);
   18746         [ #  # ]:          0 :                         if (!mtrmng->drop_tbl[domain]) {
   18747                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter "
   18748                 :            :                                         "drop table for default policy.");
   18749                 :          0 :                                 goto def_policy_error;
   18750                 :            :                         }
   18751                 :            :                 }
   18752                 :            :                 /* all RED: unique Drop table for jump action. */
   18753                 :          0 :                 tbl_data = container_of(mtrmng->drop_tbl[domain],
   18754                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18755                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_RED] =
   18756                 :          0 :                                                 tbl_data->jump.action;
   18757                 :          0 :                 acts[RTE_COLOR_RED].dv_actions[0] = tbl_data->jump.action;
   18758                 :          0 :                 acts[RTE_COLOR_RED].actions_n = 1;
   18759                 :            :                 /* Create default policy rules. */
   18760                 :          0 :                 ret = __flow_dv_create_domain_policy_rules(dev,
   18761                 :            :                                         &def_policy->sub_policy,
   18762                 :            :                                         egress, transfer, match_src_port, acts);
   18763         [ #  # ]:          0 :                 if (ret) {
   18764                 :          0 :                         DRV_LOG(ERR, "Failed to create default policy rules.");
   18765                 :          0 :                         goto def_policy_error;
   18766                 :            :                 }
   18767                 :            :         }
   18768                 :            :         return 0;
   18769                 :          0 : def_policy_error:
   18770                 :          0 :         __flow_dv_destroy_domain_def_policy(dev,
   18771                 :            :                                             (enum mlx5_meter_domain)domain);
   18772                 :          0 :         return -1;
   18773                 :            : }
   18774                 :            : 
   18775                 :            : /**
   18776                 :            :  * Create the default policy table set.
   18777                 :            :  *
   18778                 :            :  * @param[in] dev
   18779                 :            :  *   Pointer to Ethernet device.
   18780                 :            :  * @return
   18781                 :            :  *   0 on success, -1 otherwise.
   18782                 :            :  */
   18783                 :            : static int
   18784                 :          0 : flow_dv_create_def_policy(struct rte_eth_dev *dev)
   18785                 :            : {
   18786                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18787                 :            :         int i;
   18788                 :            : 
   18789                 :            :         /* Non-termination policy table. */
   18790         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18791   [ #  #  #  # ]:          0 :                 if (!priv->sh->config.dv_esw_en &&
   18792                 :            :                     i == MLX5_MTR_DOMAIN_TRANSFER)
   18793                 :          0 :                         continue;
   18794         [ #  # ]:          0 :                 if (__flow_dv_create_domain_def_policy(dev, i)) {
   18795                 :          0 :                         DRV_LOG(ERR, "Failed to create default policy");
   18796                 :            :                         /* Rollback the created default policies for others. */
   18797                 :          0 :                         flow_dv_destroy_def_policy(dev);
   18798                 :          0 :                         return -1;
   18799                 :            :                 }
   18800                 :            :         }
   18801                 :            :         return 0;
   18802                 :            : }
   18803                 :            : 
   18804                 :            : /**
   18805                 :            :  * Create the needed meter tables.
   18806                 :            :  * Lock free, (mutex should be acquired by caller).
   18807                 :            :  *
   18808                 :            :  * @param[in] dev
   18809                 :            :  *   Pointer to Ethernet device.
   18810                 :            :  * @param[in] fm
   18811                 :            :  *   Meter information table.
   18812                 :            :  * @param[in] mtr_idx
   18813                 :            :  *   Meter index.
   18814                 :            :  * @param[in] domain_bitmap
   18815                 :            :  *   Domain bitmap.
   18816                 :            :  * @return
   18817                 :            :  *   0 on success, -1 otherwise.
   18818                 :            :  */
   18819                 :            : static int
   18820                 :          0 : flow_dv_create_mtr_tbls(struct rte_eth_dev *dev,
   18821                 :            :                         struct mlx5_flow_meter_info *fm,
   18822                 :            :                         uint32_t mtr_idx,
   18823                 :            :                         uint8_t domain_bitmap)
   18824                 :            : {
   18825                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18826                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18827                 :            :         struct rte_flow_error error;
   18828                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18829                 :            :         uint8_t egress, transfer;
   18830                 :            :         void *actions[METER_ACTIONS];
   18831                 :            :         int domain, ret, i;
   18832                 :            :         struct mlx5_flow_counter *cnt;
   18833                 :          0 :         struct mlx5_flow_dv_match_params value = {
   18834                 :            :                 .size = sizeof(value.buf),
   18835                 :            :         };
   18836                 :          0 :         struct mlx5_flow_dv_match_params matcher_para = {
   18837                 :            :                 .size = sizeof(matcher_para.buf),
   18838                 :            :         };
   18839                 :          0 :         int mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
   18840                 :            :                                                      0, &error);
   18841                 :          0 :         uint32_t mtr_id_mask = (UINT32_C(1) << mtrmng->max_mtr_bits) - 1;
   18842                 :          0 :         uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
   18843                 :            :         struct mlx5_list_entry *entry;
   18844                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   18845                 :            :                 .mask = {
   18846                 :            :                         .size = sizeof(matcher.mask.buf),
   18847                 :            :                 },
   18848                 :            :         };
   18849                 :            :         struct mlx5_flow_dv_matcher *drop_matcher;
   18850                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   18851                 :            :                 .error = &error,
   18852                 :            :                 .data = &matcher,
   18853                 :            :         };
   18854                 :            :         uint8_t misc_mask;
   18855                 :            : 
   18856   [ #  #  #  # ]:          0 :         if (!priv->mtr_en || mtr_id_reg_c < 0) {
   18857                 :          0 :                 rte_errno = ENOTSUP;
   18858                 :          0 :                 return -1;
   18859                 :            :         }
   18860         [ #  # ]:          0 :         for (domain = 0; domain < MLX5_MTR_DOMAIN_MAX; domain++) {
   18861         [ #  # ]:          0 :                 if (!(domain_bitmap & (1 << domain)) ||
   18862   [ #  #  #  # ]:          0 :                         (mtrmng->def_rule[domain] && !fm->drop_cnt))
   18863                 :          0 :                         continue;
   18864                 :          0 :                 egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18865                 :          0 :                 transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18866                 :            :                 /* Create the drop table with METER DROP level. */
   18867         [ #  # ]:          0 :                 if (!mtrmng->drop_tbl[domain]) {
   18868                 :          0 :                         mtrmng->drop_tbl[domain] = flow_dv_tbl_resource_get(dev,
   18869                 :            :                                         MLX5_FLOW_TABLE_LEVEL_METER,
   18870                 :            :                                         egress, transfer, false, NULL, 0,
   18871                 :            :                                         0, MLX5_MTR_TABLE_ID_DROP, &error);
   18872         [ #  # ]:          0 :                         if (!mtrmng->drop_tbl[domain]) {
   18873                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter drop table.");
   18874                 :          0 :                                 goto policy_error;
   18875                 :            :                         }
   18876                 :            :                 }
   18877                 :            :                 /* Create default matcher in drop table. */
   18878                 :          0 :                 matcher.tbl = mtrmng->drop_tbl[domain],
   18879                 :          0 :                 tbl_data = container_of(mtrmng->drop_tbl[domain],
   18880                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   18881         [ #  # ]:          0 :                 if (!mtrmng->def_matcher[domain]) {
   18882                 :          0 :                         flow_dv_match_meta_reg_all(matcher.mask.buf, value.buf,
   18883                 :            :                                        (enum modify_reg)mtr_id_reg_c,
   18884                 :            :                                        0, 0);
   18885                 :          0 :                         matcher.priority = MLX5_MTRS_DEFAULT_RULE_PRIORITY;
   18886                 :          0 :                         matcher.crc = rte_raw_cksum
   18887                 :            :                                         ((const void *)matcher.mask.buf,
   18888                 :            :                                         matcher.mask.size);
   18889                 :          0 :                         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18890         [ #  # ]:          0 :                         if (!entry) {
   18891                 :          0 :                                 DRV_LOG(ERR, "Failed to register meter "
   18892                 :            :                                 "drop default matcher.");
   18893                 :          0 :                                 goto policy_error;
   18894                 :            :                         }
   18895                 :          0 :                         mtrmng->def_matcher[domain] = container_of(entry,
   18896                 :            :                         struct mlx5_flow_dv_matcher, entry);
   18897                 :            :                 }
   18898                 :            :                 /* Create default rule in drop table. */
   18899         [ #  # ]:          0 :                 if (!mtrmng->def_rule[domain]) {
   18900                 :            :                         i = 0;
   18901                 :          0 :                         actions[i++] = priv->sh->dr_drop_action;
   18902                 :          0 :                         flow_dv_match_meta_reg_all(matcher_para.buf, value.buf,
   18903                 :            :                                 (enum modify_reg)mtr_id_reg_c, 0, 0);
   18904         [ #  # ]:          0 :                         misc_mask = flow_dv_matcher_enable(mtrmng->def_matcher[domain]->mask.buf);
   18905                 :            :                         __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18906                 :          0 :                         ret = mlx5_flow_os_create_flow
   18907                 :            :                                 (mtrmng->def_matcher[domain]->matcher_object,
   18908                 :            :                                 (void *)&value, i, actions,
   18909                 :            :                                 &mtrmng->def_rule[domain]);
   18910                 :            :                         if (ret) {
   18911                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter "
   18912                 :            :                                 "default drop rule for drop table.");
   18913                 :          0 :                                 goto policy_error;
   18914                 :            :                         }
   18915                 :            :                 }
   18916         [ #  # ]:          0 :                 if (!fm->drop_cnt)
   18917                 :          0 :                         continue;
   18918                 :            :                 MLX5_ASSERT(mtrmng->max_mtr_bits);
   18919         [ #  # ]:          0 :                 if (!mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1]) {
   18920                 :            :                         /* Create matchers for Drop. */
   18921                 :          0 :                         flow_dv_match_meta_reg_all(matcher.mask.buf, value.buf,
   18922                 :            :                                         (enum modify_reg)mtr_id_reg_c, 0,
   18923                 :            :                                         (mtr_id_mask << mtr_id_offset));
   18924                 :          0 :                         matcher.priority = MLX5_REG_BITS - mtrmng->max_mtr_bits;
   18925                 :          0 :                         matcher.crc = rte_raw_cksum
   18926                 :            :                                         ((const void *)matcher.mask.buf,
   18927                 :            :                                         matcher.mask.size);
   18928                 :          0 :                         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18929         [ #  # ]:          0 :                         if (!entry) {
   18930                 :          0 :                                 DRV_LOG(ERR,
   18931                 :            :                                 "Failed to register meter drop matcher.");
   18932                 :          0 :                                 goto policy_error;
   18933                 :            :                         }
   18934                 :          0 :                         mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1] =
   18935                 :            :                                 container_of(entry, struct mlx5_flow_dv_matcher,
   18936                 :            :                                              entry);
   18937                 :            :                 }
   18938                 :          0 :                 drop_matcher =
   18939                 :          0 :                         mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1];
   18940                 :            :                 /* Create drop rule, matching meter_id only. */
   18941                 :          0 :                 flow_dv_match_meta_reg_all(matcher_para.buf, value.buf,
   18942                 :            :                                 (enum modify_reg)mtr_id_reg_c,
   18943                 :            :                                 (mtr_idx << mtr_id_offset), UINT32_MAX);
   18944                 :            :                 i = 0;
   18945         [ #  # ]:          0 :                 cnt = flow_dv_counter_get_by_idx(dev,
   18946                 :            :                                         fm->drop_cnt, NULL);
   18947                 :          0 :                 actions[i++] = cnt->action;
   18948                 :          0 :                 actions[i++] = priv->sh->dr_drop_action;
   18949         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(drop_matcher->mask.buf);
   18950                 :            :                 __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18951                 :          0 :                 ret = mlx5_flow_os_create_flow(drop_matcher->matcher_object,
   18952                 :            :                                                (void *)&value, i, actions,
   18953                 :            :                                                &fm->drop_rule[domain]);
   18954                 :            :                 if (ret) {
   18955                 :          0 :                         DRV_LOG(ERR, "Failed to create meter "
   18956                 :            :                                 "drop rule for drop table.");
   18957                 :          0 :                                 goto policy_error;
   18958                 :            :                 }
   18959                 :            :         }
   18960                 :            :         return 0;
   18961                 :            : policy_error:
   18962         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18963         [ #  # ]:          0 :                 if (fm->drop_rule[i]) {
   18964                 :            :                         claim_zero(mlx5_flow_os_destroy_flow
   18965                 :            :                                 (fm->drop_rule[i]));
   18966                 :          0 :                         fm->drop_rule[i] = NULL;
   18967                 :            :                 }
   18968                 :            :         }
   18969                 :            :         return -1;
   18970                 :            : }
   18971                 :            : 
   18972                 :            : static struct mlx5_flow_meter_sub_policy *
   18973                 :          0 : __flow_dv_meter_get_rss_sub_policy(struct rte_eth_dev *dev,
   18974                 :            :                 struct mlx5_flow_meter_policy *mtr_policy,
   18975                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS],
   18976                 :            :                 struct mlx5_flow_meter_sub_policy *next_sub_policy,
   18977                 :            :                 bool *is_reuse)
   18978                 :            : {
   18979                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18980                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   18981                 :          0 :         uint32_t sub_policy_idx = 0;
   18982                 :          0 :         uint32_t hrxq_idx[MLX5_MTR_RTE_COLORS] = {0};
   18983                 :            :         uint32_t i, j;
   18984                 :            :         struct mlx5_hrxq *hrxq;
   18985                 :            :         struct mlx5_flow_handle dh;
   18986                 :            :         struct mlx5_meter_policy_action_container *act_cnt;
   18987                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   18988                 :            :         uint16_t sub_policy_num;
   18989                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   18990                 :            : 
   18991                 :            :         MLX5_ASSERT(wks);
   18992                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   18993         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   18994         [ #  # ]:          0 :                 if (!rss_desc[i])
   18995                 :          0 :                         continue;
   18996                 :          0 :                 hrxq = mlx5_hrxq_get(dev, rss_desc[i]);
   18997         [ #  # ]:          0 :                 if (!hrxq) {
   18998                 :            :                         rte_spinlock_unlock(&mtr_policy->sl);
   18999                 :          0 :                         return NULL;
   19000                 :            :                 }
   19001                 :          0 :                 hrxq_idx[i] = hrxq->idx;
   19002                 :            :         }
   19003                 :          0 :         sub_policy_num = (mtr_policy->sub_policy_num >>
   19004                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19005                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19006         [ #  # ]:          0 :         for (j = 0; j < sub_policy_num; j++) {
   19007         [ #  # ]:          0 :                 for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19008         [ #  # ]:          0 :                         if (rss_desc[i] &&
   19009                 :          0 :                             hrxq_idx[i] !=
   19010         [ #  # ]:          0 :                             mtr_policy->sub_policys[domain][j]->rix_hrxq[i])
   19011                 :            :                                 break;
   19012                 :            :                 }
   19013         [ #  # ]:          0 :                 if (i >= MLX5_MTR_RTE_COLORS) {
   19014                 :            :                         /*
   19015                 :            :                          * Found the sub policy table with
   19016                 :            :                          * the same queue per color.
   19017                 :            :                          */
   19018                 :            :                         rte_spinlock_unlock(&mtr_policy->sl);
   19019         [ #  # ]:          0 :                         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++)
   19020                 :          0 :                                 mlx5_hrxq_release(dev, hrxq_idx[i]);
   19021                 :          0 :                         *is_reuse = true;
   19022                 :          0 :                         return mtr_policy->sub_policys[domain][j];
   19023                 :            :                 }
   19024                 :            :         }
   19025                 :            :         /* Create sub policy. */
   19026         [ #  # ]:          0 :         if (!mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_GREEN] &&
   19027                 :            :             !mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_YELLOW]) {
   19028                 :            :                 /* Reuse the first pre-allocated sub_policy. */
   19029                 :            :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19030                 :          0 :                 sub_policy_idx = sub_policy->idx;
   19031                 :            :         } else {
   19032                 :          0 :                 sub_policy = mlx5_ipool_zmalloc
   19033                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19034                 :            :                                  &sub_policy_idx);
   19035         [ #  # ]:          0 :                 if (!sub_policy ||
   19036         [ #  # ]:          0 :                     sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM) {
   19037         [ #  # ]:          0 :                         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++)
   19038                 :          0 :                                 mlx5_hrxq_release(dev, hrxq_idx[i]);
   19039                 :          0 :                         goto rss_sub_policy_error;
   19040                 :            :                 }
   19041                 :          0 :                 sub_policy->idx = sub_policy_idx;
   19042                 :          0 :                 sub_policy->main_policy = mtr_policy;
   19043                 :            :         }
   19044         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19045         [ #  # ]:          0 :                 if (!rss_desc[i])
   19046                 :          0 :                         continue;
   19047                 :          0 :                 sub_policy->rix_hrxq[i] = hrxq_idx[i];
   19048         [ #  # ]:          0 :                 if (mtr_policy->is_hierarchy) {
   19049                 :            :                         act_cnt = &mtr_policy->act_cnt[i];
   19050                 :          0 :                         act_cnt->next_sub_policy = next_sub_policy;
   19051                 :          0 :                         mlx5_hrxq_release(dev, hrxq_idx[i]);
   19052                 :            :                 } else {
   19053                 :            :                         /*
   19054                 :            :                          * Overwrite the last action from
   19055                 :            :                          * RSS action to Queue action.
   19056                 :            :                          */
   19057                 :          0 :                         hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
   19058                 :            :                                               hrxq_idx[i]);
   19059         [ #  # ]:          0 :                         if (!hrxq) {
   19060                 :          0 :                                 DRV_LOG(ERR, "Failed to get policy hrxq");
   19061                 :          0 :                                 goto rss_sub_policy_error;
   19062                 :            :                         }
   19063                 :            :                         act_cnt = &mtr_policy->act_cnt[i];
   19064   [ #  #  #  # ]:          0 :                         if (act_cnt->rix_mark || act_cnt->modify_hdr) {
   19065                 :            :                                 memset(&dh, 0, sizeof(struct mlx5_flow_handle));
   19066         [ #  # ]:          0 :                                 if (act_cnt->rix_mark)
   19067                 :          0 :                                         wks->mark = 1;
   19068                 :          0 :                                 dh.fate_action = MLX5_FLOW_FATE_QUEUE;
   19069                 :          0 :                                 dh.rix_hrxq = hrxq_idx[i];
   19070                 :          0 :                                 flow_drv_rxq_flags_set(dev, &dh);
   19071                 :            :                         }
   19072                 :            :                 }
   19073                 :            :         }
   19074         [ #  # ]:          0 :         if (__flow_dv_create_policy_acts_rules(dev, mtr_policy,
   19075                 :            :                                                sub_policy, domain)) {
   19076                 :          0 :                 DRV_LOG(ERR, "Failed to create policy "
   19077                 :            :                         "rules for ingress domain.");
   19078                 :          0 :                 goto rss_sub_policy_error;
   19079                 :            :         }
   19080         [ #  # ]:          0 :         if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19081                 :          0 :                 i = (mtr_policy->sub_policy_num >>
   19082                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19083                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19084         [ #  # ]:          0 :                 if (i >= MLX5_MTR_RSS_MAX_SUB_POLICY) {
   19085                 :          0 :                         DRV_LOG(ERR, "No free sub-policy slot.");
   19086                 :          0 :                         goto rss_sub_policy_error;
   19087                 :            :                 }
   19088                 :          0 :                 mtr_policy->sub_policys[domain][i] = sub_policy;
   19089                 :          0 :                 i++;
   19090                 :          0 :                 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19091                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain));
   19092                 :          0 :                 mtr_policy->sub_policy_num |=
   19093                 :          0 :                         (i & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19094                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain);
   19095                 :            :         }
   19096                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19097                 :          0 :         *is_reuse = false;
   19098                 :          0 :         return sub_policy;
   19099                 :          0 : rss_sub_policy_error:
   19100         [ #  # ]:          0 :         if (sub_policy) {
   19101                 :          0 :                 __flow_dv_destroy_sub_policy_rules(dev, sub_policy);
   19102         [ #  # ]:          0 :                 if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19103                 :          0 :                         i = (mtr_policy->sub_policy_num >>
   19104                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19105                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19106                 :          0 :                         mtr_policy->sub_policys[domain][i] = NULL;
   19107                 :          0 :                         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19108                 :          0 :                                         sub_policy->idx);
   19109                 :            :                 }
   19110                 :            :         }
   19111                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19112                 :          0 :         return NULL;
   19113                 :            : }
   19114                 :            : 
   19115                 :            : /**
   19116                 :            :  * Find the policy table for prefix table with RSS.
   19117                 :            :  *
   19118                 :            :  * @param[in] dev
   19119                 :            :  *   Pointer to Ethernet device.
   19120                 :            :  * @param[in] mtr_policy
   19121                 :            :  *   Pointer to meter policy table.
   19122                 :            :  * @param[in] rss_desc
   19123                 :            :  *   Pointer to rss_desc
   19124                 :            :  * @return
   19125                 :            :  *   Pointer to table set on success, NULL otherwise and rte_errno is set.
   19126                 :            :  */
   19127                 :            : static struct mlx5_flow_meter_sub_policy *
   19128                 :          0 : flow_dv_meter_sub_policy_rss_prepare(struct rte_eth_dev *dev,
   19129                 :            :                 struct mlx5_flow_meter_policy *mtr_policy,
   19130                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS])
   19131                 :            : {
   19132                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19133                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   19134                 :            :         struct mlx5_flow_meter_info *next_fm;
   19135                 :            :         struct mlx5_flow_meter_policy *next_policy;
   19136                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy = NULL;
   19137                 :            :         struct mlx5_flow_meter_policy *policies[MLX5_MTR_CHAIN_MAX_NUM];
   19138                 :            :         struct mlx5_flow_meter_sub_policy *sub_policies[MLX5_MTR_CHAIN_MAX_NUM];
   19139                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   19140                 :            :         bool reuse_sub_policy;
   19141                 :            :         uint32_t i = 0;
   19142                 :            :         uint32_t j = 0;
   19143                 :            : 
   19144                 :            :         while (true) {
   19145                 :            :                 /* Iterate hierarchy to get all policies in this hierarchy. */
   19146                 :          0 :                 policies[i++] = mtr_policy;
   19147         [ #  # ]:          0 :                 if (!mtr_policy->is_hierarchy)
   19148                 :            :                         break;
   19149         [ #  # ]:          0 :                 if (i >= MLX5_MTR_CHAIN_MAX_NUM) {
   19150                 :          0 :                         DRV_LOG(ERR, "Exceed max meter number in hierarchy.");
   19151                 :          0 :                         return NULL;
   19152                 :            :                 }
   19153                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19154                 :          0 :                 next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, mtr_policy, NULL);
   19155                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19156         [ #  # ]:          0 :                 if (!next_fm) {
   19157                 :          0 :                         DRV_LOG(ERR, "Failed to get next meter in hierarchy.");
   19158                 :          0 :                         return NULL;
   19159                 :            :                 }
   19160                 :            :                 next_policy =
   19161                 :          0 :                         mlx5_flow_meter_policy_find(dev, next_fm->policy_id,
   19162                 :            :                                                     NULL);
   19163                 :            :                 MLX5_ASSERT(next_policy);
   19164                 :            :                 mtr_policy = next_policy;
   19165                 :            :         }
   19166         [ #  # ]:          0 :         while (i) {
   19167                 :            :                 /**
   19168                 :            :                  * From last policy to the first one in hierarchy,
   19169                 :            :                  * create / get the sub policy for each of them.
   19170                 :            :                  */
   19171                 :          0 :                 sub_policy = __flow_dv_meter_get_rss_sub_policy(dev,
   19172                 :            :                                                         policies[--i],
   19173                 :            :                                                         rss_desc,
   19174                 :            :                                                         next_sub_policy,
   19175                 :            :                                                         &reuse_sub_policy);
   19176         [ #  # ]:          0 :                 if (!sub_policy) {
   19177                 :          0 :                         DRV_LOG(ERR, "Failed to get the sub policy.");
   19178                 :          0 :                         goto err_exit;
   19179                 :            :                 }
   19180         [ #  # ]:          0 :                 if (!reuse_sub_policy)
   19181                 :          0 :                         sub_policies[j++] = sub_policy;
   19182                 :            :                 next_sub_policy = sub_policy;
   19183                 :            :         }
   19184                 :            :         return sub_policy;
   19185                 :            : err_exit:
   19186         [ #  # ]:          0 :         while (j) {
   19187                 :            :                 uint16_t sub_policy_num;
   19188                 :            : 
   19189                 :          0 :                 sub_policy = sub_policies[--j];
   19190                 :          0 :                 mtr_policy = sub_policy->main_policy;
   19191                 :          0 :                 __flow_dv_destroy_sub_policy_rules(dev, sub_policy);
   19192         [ #  # ]:          0 :                 if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19193                 :          0 :                         sub_policy_num = (mtr_policy->sub_policy_num >>
   19194                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19195                 :            :                                 MLX5_MTR_SUB_POLICY_NUM_MASK;
   19196                 :          0 :                         mtr_policy->sub_policys[domain][sub_policy_num - 1] =
   19197                 :            :                                                                         NULL;
   19198                 :          0 :                         sub_policy_num--;
   19199                 :          0 :                         mtr_policy->sub_policy_num &=
   19200                 :          0 :                                 ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19201                 :          0 :                                   (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
   19202                 :          0 :                         mtr_policy->sub_policy_num |=
   19203                 :          0 :                         (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19204                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
   19205                 :          0 :                         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19206                 :          0 :                                         sub_policy->idx);
   19207                 :            :                 }
   19208                 :            :         }
   19209                 :            :         return NULL;
   19210                 :            : }
   19211                 :            : 
   19212                 :            : /**
   19213                 :            :  * Check if need to create hierarchy tag rule.
   19214                 :            :  *
   19215                 :            :  * @param[in] priv
   19216                 :            :  *   Pointer to mlx5_priv.
   19217                 :            :  * @param[in] mtr_policy
   19218                 :            :  *   Pointer to current meter policy.
   19219                 :            :  * @param[in] src_port
   19220                 :            :  *   The src port this extra rule should use.
   19221                 :            :  * @param[out] next_fm
   19222                 :            :  *   Pointer to next meter in hierarchy.
   19223                 :            :  * @param[out] skip
   19224                 :            :  *   Indicate if skip the tag rule creation.
   19225                 :            :  * @param[out] error
   19226                 :            :  *   Perform verbose error reporting if not NULL.
   19227                 :            :  * @return
   19228                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19229                 :            :  */
   19230                 :            : static int
   19231                 :          0 : mlx5_meter_hierarchy_skip_tag_rule(struct mlx5_priv *priv,
   19232                 :            :                                    struct mlx5_flow_meter_policy *mtr_policy,
   19233                 :            :                                    int32_t src_port,
   19234                 :            :                                    struct mlx5_flow_meter_info **next_fm,
   19235                 :            :                                    bool *skip,
   19236                 :            :                                    struct rte_flow_error *error)
   19237                 :            : {
   19238                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   19239                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   19240                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_TRANSFER;
   19241                 :            :         int ret = 0;
   19242                 :            :         int i;
   19243                 :            : 
   19244                 :          0 :         *next_fm = NULL;
   19245                 :          0 :         *skip = false;
   19246                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   19247         [ #  # ]:          0 :         if (mtr_policy->is_hierarchy) {
   19248                 :          0 :                 *next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, mtr_policy, NULL);
   19249         [ #  # ]:          0 :                 if (!*next_fm) {
   19250                 :          0 :                         ret = rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   19251                 :            :                                                 NULL, "Failed to find next meter in hierarchy.");
   19252                 :          0 :                         goto exit;
   19253                 :            :                 }
   19254                 :            :         }
   19255         [ #  # ]:          0 :         if (!mtr_policy->match_port) {
   19256                 :          0 :                 *skip = true;
   19257                 :          0 :                 goto exit;
   19258                 :            :         }
   19259                 :          0 :         sub_policy = mtr_policy->sub_policys[domain][0];
   19260         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19261         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action != MLX5_FLOW_FATE_MTR &&
   19262                 :            :                     mtr_policy->act_cnt[i].fate_action != MLX5_FLOW_FATE_PORT_ID)
   19263                 :          0 :                         continue;
   19264         [ #  # ]:          0 :                 TAILQ_FOREACH(color_rule, &sub_policy->color_rules[i], next_port)
   19265         [ #  # ]:          0 :                         if (color_rule->src_port == src_port) {
   19266                 :          0 :                                 *skip = true;
   19267                 :          0 :                                 goto exit;
   19268                 :            :                         }
   19269                 :            :         }
   19270                 :          0 : exit:
   19271                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19272                 :          0 :         return ret;
   19273                 :            : }
   19274                 :            : 
   19275                 :            : /**
   19276                 :            :  * Create the sub policy tag rule for all meters in hierarchy.
   19277                 :            :  *
   19278                 :            :  * @param[in] dev
   19279                 :            :  *   Pointer to Ethernet device.
   19280                 :            :  * @param[in] fm
   19281                 :            :  *   Meter information table.
   19282                 :            :  * @param[in] src_port
   19283                 :            :  *   The src port this extra rule should use.
   19284                 :            :  * @param[in] item
   19285                 :            :  *   The src port match item.
   19286                 :            :  * @param[out] error
   19287                 :            :  *   Perform verbose error reporting if not NULL.
   19288                 :            :  * @return
   19289                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19290                 :            :  */
   19291                 :            : static int
   19292                 :          0 : flow_dv_meter_hierarchy_rule_create(struct rte_eth_dev *dev,
   19293                 :            :                                 struct mlx5_flow_meter_info *fm,
   19294                 :            :                                 int32_t src_port,
   19295                 :            :                                 const struct rte_flow_item *item,
   19296                 :            :                                 struct rte_flow_error *error)
   19297                 :            : {
   19298                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19299                 :            :         struct mlx5_flow_meter_policy *mtr_policy;
   19300                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   19301                 :          0 :         struct mlx5_flow_meter_info *next_fm = NULL;
   19302                 :            :         struct mlx5_flow_meter_policy *next_policy;
   19303                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy;
   19304                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   19305                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   19306                 :            :         struct mlx5_meter_policy_acts acts;
   19307                 :            :         uint32_t color_reg_c_idx;
   19308                 :            :         bool mtr_first = (src_port != UINT16_MAX) ? true : false;
   19309                 :          0 :         struct rte_flow_attr attr = {
   19310                 :            :                 .group = MLX5_FLOW_TABLE_LEVEL_POLICY,
   19311                 :            :                 .priority = 0,
   19312                 :            :                 .ingress = 0,
   19313                 :            :                 .egress = 0,
   19314                 :            :                 .transfer = 1,
   19315                 :            :                 .reserved = 0,
   19316                 :            :         };
   19317                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_TRANSFER;
   19318                 :            :         struct {
   19319                 :            :                 struct mlx5_flow_meter_policy *fm_policy;
   19320                 :            :                 struct mlx5_flow_meter_info *next_fm;
   19321                 :            :                 struct mlx5_sub_policy_color_rule *tag_rule[RTE_COLORS];
   19322                 :          0 :         } fm_info[MLX5_MTR_CHAIN_MAX_NUM] = { {0} };
   19323                 :            :         uint32_t fm_cnt = 0;
   19324                 :            :         uint32_t i, j;
   19325                 :            : 
   19326                 :          0 :         color_reg_c_idx = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, error);
   19327                 :            :         /* Get all fms who need to create the tag color rule. */
   19328                 :            :         do {
   19329                 :          0 :                 bool skip = false;
   19330                 :            : 
   19331                 :          0 :                 mtr_policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
   19332                 :            :                 MLX5_ASSERT(mtr_policy);
   19333         [ #  # ]:          0 :                 if (mlx5_meter_hierarchy_skip_tag_rule(priv, mtr_policy, src_port,
   19334                 :            :                                                        &next_fm, &skip, error))
   19335                 :          0 :                         goto err_exit;
   19336         [ #  # ]:          0 :                 if (!skip) {
   19337                 :          0 :                         fm_info[fm_cnt].fm_policy = mtr_policy;
   19338                 :          0 :                         fm_info[fm_cnt].next_fm = next_fm;
   19339         [ #  # ]:          0 :                         if (++fm_cnt >= MLX5_MTR_CHAIN_MAX_NUM) {
   19340                 :          0 :                                 rte_flow_error_set(error, errno,
   19341                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19342                 :            :                                         "Exceed max meter number in hierarchy.");
   19343                 :          0 :                                 goto err_exit;
   19344                 :            :                         }
   19345                 :            :                 }
   19346                 :          0 :                 fm = next_fm;
   19347         [ #  # ]:          0 :         } while (fm);
   19348                 :            :         /* Create tag color rules for all needed fms. */
   19349         [ #  # ]:          0 :         for (i = 0; i < fm_cnt; i++) {
   19350                 :            :                 void *mtr_action;
   19351                 :            : 
   19352                 :          0 :                 mtr_policy = fm_info[i].fm_policy;
   19353                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19354                 :          0 :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19355         [ #  # ]:          0 :                 for (j = 0; j < RTE_COLORS; j++) {
   19356                 :            :                         uint8_t act_n = 0;
   19357                 :            :                         struct mlx5_flow_dv_modify_hdr_resource *modify_hdr = NULL;
   19358                 :            :                         struct mlx5_flow_dv_port_id_action_resource *port_action;
   19359                 :            :                         uint8_t fate_action;
   19360                 :            : 
   19361         [ #  # ]:          0 :                         if (j == RTE_COLOR_RED) {
   19362                 :            :                                 fate_action = MLX5_FLOW_FATE_DROP;
   19363                 :            :                         } else {
   19364                 :          0 :                                 fate_action = mtr_policy->act_cnt[j].fate_action;
   19365                 :          0 :                                 modify_hdr = mtr_policy->act_cnt[j].modify_hdr;
   19366                 :          0 :                                 if (fate_action != MLX5_FLOW_FATE_MTR &&
   19367   [ #  #  #  # ]:          0 :                                     fate_action != MLX5_FLOW_FATE_PORT_ID &&
   19368                 :            :                                     fate_action != MLX5_FLOW_FATE_DROP)
   19369                 :          0 :                                         continue;
   19370                 :            :                         }
   19371                 :          0 :                         color_rule = mlx5_malloc(MLX5_MEM_ZERO,
   19372                 :            :                                                  sizeof(struct mlx5_sub_policy_color_rule),
   19373                 :            :                                                  0, SOCKET_ID_ANY);
   19374         [ #  # ]:          0 :                         if (!color_rule) {
   19375                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19376                 :          0 :                                 rte_flow_error_set(error, ENOMEM,
   19377                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   19378                 :            :                                                    "No memory to create tag color rule.");
   19379                 :          0 :                                 goto err_exit;
   19380                 :            :                         }
   19381                 :          0 :                         color_rule->src_port = src_port;
   19382                 :            :                         /* Prepare to create color rule. */
   19383         [ #  # ]:          0 :                         if (fate_action == MLX5_FLOW_FATE_MTR) {
   19384                 :          0 :                                 next_fm = fm_info[i].next_fm;
   19385         [ #  # ]:          0 :                                 if (mlx5_flow_meter_attach(priv, next_fm, &attr, error)) {
   19386                 :          0 :                                         mlx5_free(color_rule);
   19387                 :            :                                         rte_spinlock_unlock(&mtr_policy->sl);
   19388                 :          0 :                                         goto err_exit;
   19389                 :            :                                 }
   19390         [ #  # ]:          0 :                                 mtr_action = (next_fm->color_aware && j == RTE_COLOR_YELLOW) ?
   19391         [ #  # ]:          0 :                                                                         next_fm->meter_action_y :
   19392                 :            :                                                                         next_fm->meter_action_g;
   19393                 :          0 :                                 next_policy = mlx5_flow_meter_policy_find(dev, next_fm->policy_id,
   19394                 :            :                                                                           NULL);
   19395                 :            :                                 MLX5_ASSERT(next_policy);
   19396                 :          0 :                                 next_sub_policy = next_policy->sub_policys[domain][0];
   19397                 :          0 :                                 tbl_data = container_of(next_sub_policy->tbl_rsc,
   19398                 :            :                                                         struct mlx5_flow_tbl_data_entry, tbl);
   19399         [ #  # ]:          0 :                                 if (mtr_first) {
   19400                 :          0 :                                         acts.dv_actions[act_n++] = mtr_action;
   19401         [ #  # ]:          0 :                                         if (modify_hdr)
   19402                 :          0 :                                                 acts.dv_actions[act_n++] = modify_hdr->action;
   19403                 :            :                                 } else {
   19404         [ #  # ]:          0 :                                         if (modify_hdr)
   19405                 :          0 :                                                 acts.dv_actions[act_n++] = modify_hdr->action;
   19406                 :          0 :                                         acts.dv_actions[act_n++] = mtr_action;
   19407                 :            :                                 }
   19408                 :          0 :                                 acts.dv_actions[act_n++] = tbl_data->jump.action;
   19409                 :          0 :                                 acts.actions_n = act_n;
   19410         [ #  # ]:          0 :                         } else if (fate_action == MLX5_FLOW_FATE_PORT_ID) {
   19411                 :            :                                 port_action =
   19412                 :          0 :                                         mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID],
   19413                 :            :                                                        mtr_policy->act_cnt[j].rix_port_id_action);
   19414         [ #  # ]:          0 :                                 if (!port_action) {
   19415                 :          0 :                                         mlx5_free(color_rule);
   19416                 :            :                                         rte_spinlock_unlock(&mtr_policy->sl);
   19417                 :          0 :                                         goto err_exit;
   19418                 :            :                                 }
   19419         [ #  # ]:          0 :                                 if (modify_hdr)
   19420                 :          0 :                                         acts.dv_actions[act_n++] = modify_hdr->action;
   19421                 :          0 :                                 acts.dv_actions[act_n++] = port_action->action;
   19422                 :          0 :                                 acts.actions_n = act_n;
   19423                 :            :                         } else {
   19424                 :          0 :                                 acts.dv_actions[act_n++] = mtr_policy->dr_drop_action[domain];
   19425                 :          0 :                                 acts.actions_n = act_n;
   19426                 :            :                         }
   19427                 :          0 :                         fm_info[i].tag_rule[j] = color_rule;
   19428                 :          0 :                         TAILQ_INSERT_TAIL(&sub_policy->color_rules[j], color_rule, next_port);
   19429         [ #  # ]:          0 :                         if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
   19430                 :            :                                                 MLX5_MTR_POLICY_MATCHER_PRIO, sub_policy,
   19431                 :            :                                                 &attr, true, item, &color_rule->matcher, error)) {
   19432                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19433                 :          0 :                                 rte_flow_error_set(error, errno,
   19434                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19435                 :            :                                                    "Failed to create hierarchy meter matcher.");
   19436                 :          0 :                                 goto err_exit;
   19437                 :            :                         }
   19438         [ #  # ]:          0 :                         if (__flow_dv_create_policy_flow(dev, color_reg_c_idx, (enum rte_color)j,
   19439                 :            :                                                 color_rule->matcher,
   19440                 :          0 :                                                 acts.actions_n, acts.dv_actions,
   19441                 :            :                                                 true, item, &color_rule->rule, &attr)) {
   19442                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19443                 :          0 :                                 rte_flow_error_set(error, errno,
   19444                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19445                 :            :                                                    "Failed to create hierarchy meter rule.");
   19446                 :          0 :                                 goto err_exit;
   19447                 :            :                         }
   19448                 :            :                 }
   19449                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19450                 :            :         }
   19451                 :            :         return 0;
   19452                 :          0 : err_exit:
   19453         [ #  # ]:          0 :         for (i = 0; i < fm_cnt; i++) {
   19454                 :          0 :                 mtr_policy = fm_info[i].fm_policy;
   19455                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19456                 :          0 :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19457         [ #  # ]:          0 :                 for (j = 0; j < RTE_COLORS; j++) {
   19458                 :          0 :                         color_rule = fm_info[i].tag_rule[j];
   19459         [ #  # ]:          0 :                         if (!color_rule)
   19460                 :          0 :                                 continue;
   19461         [ #  # ]:          0 :                         if (color_rule->rule)
   19462                 :            :                                 mlx5_flow_os_destroy_flow(color_rule->rule);
   19463         [ #  # ]:          0 :                         if (color_rule->matcher) {
   19464                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl =
   19465                 :          0 :                                         container_of(color_rule->matcher->tbl, typeof(*tbl), tbl);
   19466                 :          0 :                                 mlx5_list_unregister(tbl->matchers, &color_rule->matcher->entry);
   19467                 :            :                         }
   19468         [ #  # ]:          0 :                         if (fm_info[i].next_fm)
   19469                 :          0 :                                 mlx5_flow_meter_detach(priv, fm_info[i].next_fm);
   19470         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[j], color_rule, next_port);
   19471                 :          0 :                         mlx5_free(color_rule);
   19472                 :            :                 }
   19473                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19474                 :            :         }
   19475                 :          0 :         return -rte_errno;
   19476                 :            : }
   19477                 :            : 
   19478                 :            : /**
   19479                 :            :  * Destroy the sub policy table with RX queue.
   19480                 :            :  *
   19481                 :            :  * @param[in] dev
   19482                 :            :  *   Pointer to Ethernet device.
   19483                 :            :  * @param[in] mtr_policy
   19484                 :            :  *   Pointer to meter policy table.
   19485                 :            :  */
   19486                 :            : static void
   19487                 :          0 : flow_dv_destroy_sub_policy_with_rxq(struct rte_eth_dev *dev,
   19488                 :            :                                     struct mlx5_flow_meter_policy *mtr_policy)
   19489                 :            : {
   19490                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19491                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   19492                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   19493                 :            :         uint32_t i, j;
   19494                 :            :         uint16_t sub_policy_num, new_policy_num;
   19495                 :            : 
   19496                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   19497         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19498      [ #  #  # ]:          0 :                 switch (mtr_policy->act_cnt[i].fate_action) {
   19499                 :          0 :                 case MLX5_FLOW_FATE_SHARED_RSS:
   19500                 :          0 :                         sub_policy_num = (mtr_policy->sub_policy_num >>
   19501                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19502                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19503                 :            :                         new_policy_num = sub_policy_num;
   19504         [ #  # ]:          0 :                         for (j = 0; j < sub_policy_num; j++) {
   19505                 :          0 :                                 sub_policy =
   19506                 :          0 :                                         mtr_policy->sub_policys[domain][j];
   19507         [ #  # ]:          0 :                                 if (sub_policy) {
   19508                 :          0 :                                         __flow_dv_destroy_sub_policy_rules(dev,
   19509                 :            :                                                 sub_policy);
   19510                 :          0 :                                 if (sub_policy !=
   19511         [ #  # ]:          0 :                                         mtr_policy->sub_policys[domain][0]) {
   19512                 :          0 :                                         mtr_policy->sub_policys[domain][j] =
   19513                 :            :                                                                 NULL;
   19514                 :          0 :                                         mlx5_ipool_free
   19515                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19516                 :          0 :                                                 sub_policy->idx);
   19517                 :          0 :                                                 new_policy_num--;
   19518                 :            :                                         }
   19519                 :            :                                 }
   19520                 :            :                         }
   19521         [ #  # ]:          0 :                         if (new_policy_num != sub_policy_num) {
   19522                 :          0 :                                 mtr_policy->sub_policy_num &=
   19523                 :            :                                 ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19524                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain));
   19525                 :          0 :                                 mtr_policy->sub_policy_num |=
   19526                 :            :                                 (new_policy_num &
   19527                 :            :                                         MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19528                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain);
   19529                 :            :                         }
   19530                 :            :                         break;
   19531                 :          0 :                 case MLX5_FLOW_FATE_QUEUE:
   19532                 :          0 :                         sub_policy = mtr_policy->sub_policys[domain][0];
   19533                 :          0 :                         __flow_dv_destroy_sub_policy_rules(dev,
   19534                 :            :                                                            sub_policy);
   19535                 :          0 :                         break;
   19536                 :            :                 default:
   19537                 :            :                         /*Other actions without queue and do nothing*/
   19538                 :            :                         break;
   19539                 :            :                 }
   19540                 :            :         }
   19541                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19542                 :          0 : }
   19543                 :            : /**
   19544                 :            :  * Check whether the DR drop action is supported on the root table or not.
   19545                 :            :  *
   19546                 :            :  * Create a simple flow with DR drop action on root table to validate
   19547                 :            :  * if DR drop action on root table is supported or not.
   19548                 :            :  *
   19549                 :            :  * @param[in] dev
   19550                 :            :  *   Pointer to rte_eth_dev structure.
   19551                 :            :  *
   19552                 :            :  * @return
   19553                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19554                 :            :  */
   19555                 :            : int
   19556                 :          0 : mlx5_flow_discover_dr_action_support(struct rte_eth_dev *dev)
   19557                 :            : {
   19558                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19559                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   19560                 :          0 :         struct mlx5_flow_dv_match_params mask = {
   19561                 :            :                 .size = sizeof(mask.buf),
   19562                 :            :         };
   19563                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19564                 :            :                 .size = sizeof(value.buf),
   19565                 :            :         };
   19566                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   19567                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   19568                 :            :                 .priority = 0,
   19569                 :            :                 .match_criteria_enable = 0,
   19570                 :            :                 .match_mask = (void *)&mask,
   19571                 :            :         };
   19572                 :            :         struct mlx5_flow_tbl_resource *tbl = NULL;
   19573                 :            :         void *matcher = NULL;
   19574                 :            :         void *flow = NULL;
   19575                 :            :         int ret = -1;
   19576                 :            : 
   19577                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, 0, 0, false, NULL,
   19578                 :            :                                         0, 0, 0, NULL);
   19579         [ #  # ]:          0 :         if (!tbl)
   19580                 :          0 :                 goto err;
   19581         [ #  # ]:          0 :         dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf);
   19582                 :            :         __flow_dv_adjust_buf_size(&mask.size, dv_attr.match_criteria_enable);
   19583                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   19584                 :            :                                                tbl->obj, &matcher);
   19585                 :            :         if (ret)
   19586                 :          0 :                 goto err;
   19587         [ #  # ]:          0 :         __flow_dv_adjust_buf_size(&value.size, dv_attr.match_criteria_enable);
   19588                 :          0 :         ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 1,
   19589                 :            :                                        &sh->dr_drop_action, &flow);
   19590                 :          0 : err:
   19591                 :            :         /*
   19592                 :            :          * If DR drop action is not supported on root table, flow create will
   19593                 :            :          * be failed with EOPNOTSUPP or EPROTONOSUPPORT.
   19594                 :            :          */
   19595         [ #  # ]:          0 :         if (!flow) {
   19596         [ #  # ]:          0 :                 if (matcher &&
   19597         [ #  # ]:          0 :                     (errno == EPROTONOSUPPORT || errno == EOPNOTSUPP))
   19598                 :          0 :                         DRV_LOG(INFO, "DR drop action is not supported in root table.");
   19599                 :            :                 else
   19600                 :          0 :                         DRV_LOG(ERR, "Unexpected error in DR drop action support detection");
   19601                 :            :                 ret = -1;
   19602                 :            :         } else {
   19603                 :            :                 claim_zero(mlx5_flow_os_destroy_flow(flow));
   19604                 :            :         }
   19605         [ #  # ]:          0 :         if (matcher)
   19606                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher));
   19607         [ #  # ]:          0 :         if (tbl)
   19608                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   19609                 :          0 :         return ret;
   19610                 :            : }
   19611                 :            : 
   19612                 :            : /**
   19613                 :            :  * Validate the batch counter support in root table.
   19614                 :            :  *
   19615                 :            :  * Create a simple flow with invalid counter and drop action on root table to
   19616                 :            :  * validate if batch counter with offset on root table is supported or not.
   19617                 :            :  *
   19618                 :            :  * @param[in] dev
   19619                 :            :  *   Pointer to rte_eth_dev structure.
   19620                 :            :  *
   19621                 :            :  * @return
   19622                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19623                 :            :  */
   19624                 :            : int
   19625                 :          0 : mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev)
   19626                 :            : {
   19627                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19628                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   19629                 :          0 :         struct mlx5_flow_dv_match_params mask = {
   19630                 :            :                 .size = sizeof(mask.buf),
   19631                 :            :         };
   19632                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19633                 :            :                 .size = sizeof(value.buf),
   19634                 :            :         };
   19635                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   19636                 :            :                 .type = IBV_FLOW_ATTR_NORMAL | IBV_FLOW_ATTR_FLAGS_EGRESS,
   19637                 :            :                 .priority = 0,
   19638                 :            :                 .match_criteria_enable = 0,
   19639                 :            :                 .match_mask = (void *)&mask,
   19640                 :            :         };
   19641                 :          0 :         void *actions[2] = { 0 };
   19642                 :            :         struct mlx5_flow_tbl_resource *tbl = NULL;
   19643                 :            :         struct mlx5_devx_obj *dcs = NULL;
   19644                 :            :         void *matcher = NULL;
   19645                 :            :         void *flow = NULL;
   19646                 :            :         int ret = -1;
   19647                 :            : 
   19648                 :          0 :         tbl = flow_dv_tbl_resource_get(dev, 0, 1, 0, false, NULL,
   19649                 :            :                                         0, 0, 0, NULL);
   19650         [ #  # ]:          0 :         if (!tbl)
   19651                 :          0 :                 goto err;
   19652                 :          0 :         dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0x4);
   19653         [ #  # ]:          0 :         if (!dcs)
   19654                 :          0 :                 goto err;
   19655                 :          0 :         ret = mlx5_flow_os_create_flow_action_count(dcs->obj, UINT16_MAX,
   19656                 :            :                                                     &actions[0]);
   19657                 :            :         if (ret)
   19658                 :          0 :                 goto err;
   19659         [ #  # ]:          0 :         dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf);
   19660                 :            :         __flow_dv_adjust_buf_size(&mask.size, dv_attr.match_criteria_enable);
   19661                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   19662                 :            :                                                tbl->obj, &matcher);
   19663                 :            :         if (ret)
   19664                 :          0 :                 goto err;
   19665         [ #  # ]:          0 :         __flow_dv_adjust_buf_size(&value.size, dv_attr.match_criteria_enable);
   19666                 :            :         ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 1,
   19667                 :            :                                        actions, &flow);
   19668                 :          0 : err:
   19669                 :            :         /*
   19670                 :            :          * If batch counter with offset is not supported, the driver will not
   19671                 :            :          * validate the invalid offset value, flow create should success.
   19672                 :            :          * In this case, it means batch counter is not supported in root table.
   19673                 :            :          *
   19674                 :            :          * Otherwise, if flow create is failed, counter offset is supported.
   19675                 :            :          */
   19676         [ #  # ]:          0 :         if (flow) {
   19677                 :          0 :                 DRV_LOG(INFO, "Batch counter is not supported in root "
   19678                 :            :                               "table. Switch to fallback mode.");
   19679                 :          0 :                 rte_errno = ENOTSUP;
   19680                 :            :                 ret = -rte_errno;
   19681                 :            :                 claim_zero(mlx5_flow_os_destroy_flow(flow));
   19682                 :            :         } else {
   19683                 :            :                 /* Check matcher to make sure validate fail at flow create. */
   19684   [ #  #  #  # ]:          0 :                 if (!matcher || (matcher && errno != EINVAL))
   19685                 :          0 :                         DRV_LOG(ERR, "Unexpected error in counter offset "
   19686                 :            :                                      "support detection");
   19687                 :            :                 ret = 0;
   19688                 :            :         }
   19689         [ #  # ]:          0 :         if (actions[0])
   19690                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action(actions[0]));
   19691         [ #  # ]:          0 :         if (matcher)
   19692                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher));
   19693         [ #  # ]:          0 :         if (tbl)
   19694                 :          0 :                 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   19695         [ #  # ]:          0 :         if (dcs)
   19696                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
   19697                 :          0 :         return ret;
   19698                 :            : }
   19699                 :            : 
   19700                 :            : /**
   19701                 :            :  * Query a devx counter.
   19702                 :            :  *
   19703                 :            :  * @param[in] dev
   19704                 :            :  *   Pointer to the Ethernet device structure.
   19705                 :            :  * @param[in] cnt
   19706                 :            :  *   Index to the flow counter.
   19707                 :            :  * @param[in] clear
   19708                 :            :  *   Set to clear the counter statistics.
   19709                 :            :  * @param[out] pkts
   19710                 :            :  *   The statistics value of packets.
   19711                 :            :  * @param[out] bytes
   19712                 :            :  *   The statistics value of bytes.
   19713                 :            :  *
   19714                 :            :  * @return
   19715                 :            :  *   0 on success, otherwise return -1.
   19716                 :            :  */
   19717                 :            : static int
   19718                 :          0 : flow_dv_counter_query(struct rte_eth_dev *dev, uint32_t counter, bool clear,
   19719                 :            :                       uint64_t *pkts, uint64_t *bytes, void **action)
   19720                 :            : {
   19721                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19722                 :            :         struct mlx5_flow_counter *cnt;
   19723                 :            :         uint64_t inn_pkts, inn_bytes;
   19724                 :            :         int ret;
   19725                 :            : 
   19726         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
   19727                 :            :                 return -1;
   19728                 :            : 
   19729                 :          0 :         ret = _flow_dv_query_count(dev, counter, &inn_pkts, &inn_bytes);
   19730         [ #  # ]:          0 :         if (ret)
   19731                 :            :                 return -1;
   19732                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, NULL);
   19733         [ #  # ]:          0 :         if (cnt && action)
   19734                 :          0 :                 *action = cnt->action;
   19735                 :            : 
   19736                 :          0 :         *pkts = inn_pkts - cnt->hits;
   19737                 :          0 :         *bytes = inn_bytes - cnt->bytes;
   19738         [ #  # ]:          0 :         if (clear) {
   19739                 :          0 :                 cnt->hits = inn_pkts;
   19740                 :          0 :                 cnt->bytes = inn_bytes;
   19741                 :            :         }
   19742                 :            :         return 0;
   19743                 :            : }
   19744                 :            : 
   19745                 :            : /**
   19746                 :            :  * Get aged-out flows.
   19747                 :            :  *
   19748                 :            :  * @param[in] dev
   19749                 :            :  *   Pointer to the Ethernet device structure.
   19750                 :            :  * @param[in] context
   19751                 :            :  *   The address of an array of pointers to the aged-out flows contexts.
   19752                 :            :  * @param[in] nb_contexts
   19753                 :            :  *   The length of context array pointers.
   19754                 :            :  * @param[out] error
   19755                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19756                 :            :  *   error only.
   19757                 :            :  *
   19758                 :            :  * @return
   19759                 :            :  *   how many contexts get in success, otherwise negative errno value.
   19760                 :            :  *   if nb_contexts is 0, return the amount of all aged contexts.
   19761                 :            :  *   if nb_contexts is not 0 , return the amount of aged flows reported
   19762                 :            :  *   in the context array.
   19763                 :            :  * @note: only stub for now
   19764                 :            :  */
   19765                 :            : static int
   19766                 :          0 : flow_dv_get_aged_flows(struct rte_eth_dev *dev,
   19767                 :            :                     void **context,
   19768                 :            :                     uint32_t nb_contexts,
   19769                 :            :                     struct rte_flow_error *error)
   19770                 :            : {
   19771                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19772                 :            :         struct mlx5_age_info *age_info;
   19773                 :            :         struct mlx5_age_param *age_param;
   19774                 :            :         struct mlx5_flow_counter *counter;
   19775                 :            :         struct mlx5_aso_age_action *act;
   19776                 :            :         int nb_flows = 0;
   19777                 :            : 
   19778         [ #  # ]:          0 :         if (nb_contexts && !context)
   19779                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   19780                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   19781                 :            :                                           NULL, "empty context");
   19782                 :          0 :         age_info = GET_PORT_AGE_INFO(priv);
   19783                 :          0 :         rte_spinlock_lock(&age_info->aged_sl);
   19784         [ #  # ]:          0 :         LIST_FOREACH(act, &age_info->aged_aso, next) {
   19785                 :          0 :                 nb_flows++;
   19786         [ #  # ]:          0 :                 if (nb_contexts) {
   19787                 :          0 :                         context[nb_flows - 1] = act->age_params.context;
   19788         [ #  # ]:          0 :                         if (!(--nb_contexts))
   19789                 :            :                                 break;
   19790                 :            :                 }
   19791                 :            :         }
   19792         [ #  # ]:          0 :         TAILQ_FOREACH(counter, &age_info->aged_counters, next) {
   19793                 :          0 :                 nb_flows++;
   19794         [ #  # ]:          0 :                 if (nb_contexts) {
   19795                 :            :                         age_param = MLX5_CNT_TO_AGE(counter);
   19796                 :          0 :                         context[nb_flows - 1] = age_param->context;
   19797         [ #  # ]:          0 :                         if (!(--nb_contexts))
   19798                 :            :                                 break;
   19799                 :            :                 }
   19800                 :            :         }
   19801                 :            :         rte_spinlock_unlock(&age_info->aged_sl);
   19802                 :          0 :         MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER);
   19803                 :          0 :         return nb_flows;
   19804                 :            : }
   19805                 :            : 
   19806                 :            : /*
   19807                 :            :  * Mutex-protected thunk to lock-free flow_dv_counter_alloc().
   19808                 :            :  */
   19809                 :            : static uint32_t
   19810                 :          0 : flow_dv_counter_allocate(struct rte_eth_dev *dev)
   19811                 :            : {
   19812                 :          0 :         return flow_dv_counter_alloc(dev, 0);
   19813                 :            : }
   19814                 :            : 
   19815                 :            : /**
   19816                 :            :  * Validate indirect action.
   19817                 :            :  * Dispatcher for action type specific validation.
   19818                 :            :  *
   19819                 :            :  * @param[in] dev
   19820                 :            :  *   Pointer to the Ethernet device structure.
   19821                 :            :  * @param[in] conf
   19822                 :            :  *   Indirect action configuration.
   19823                 :            :  * @param[in] action
   19824                 :            :  *   The indirect action object to validate.
   19825                 :            :  * @param[out] error
   19826                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19827                 :            :  *   error only.
   19828                 :            :  *
   19829                 :            :  * @return
   19830                 :            :  *   0 on success, otherwise negative errno value.
   19831                 :            :  */
   19832                 :            : int
   19833                 :          0 : flow_dv_action_validate(struct rte_eth_dev *dev,
   19834                 :            :                         const struct rte_flow_indir_action_conf *conf,
   19835                 :            :                         const struct rte_flow_action *action,
   19836                 :            :                         struct rte_flow_error *err)
   19837                 :            : {
   19838                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19839                 :            :         /* called from RTE API */
   19840                 :            : 
   19841                 :            :         RTE_SET_USED(conf);
   19842   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   19843                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   19844                 :            :                 /*
   19845                 :            :                  * priv->obj_ops is set according to driver capabilities.
   19846                 :            :                  * When DevX capabilities are
   19847                 :            :                  * sufficient, it is set to devx_obj_ops.
   19848                 :            :                  * Otherwise, it is set to ibv_obj_ops.
   19849                 :            :                  * ibv_obj_ops doesn't support ind_table_modify operation.
   19850                 :            :                  * In this case the indirect RSS action can't be used.
   19851                 :            :                  */
   19852         [ #  # ]:          0 :                 if (priv->obj_ops.ind_table_modify == NULL)
   19853                 :          0 :                         return rte_flow_error_set
   19854                 :            :                                         (err, ENOTSUP,
   19855                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   19856                 :            :                                          NULL,
   19857                 :            :                                          "Indirect RSS action not supported");
   19858                 :          0 :                 return mlx5_validate_action_rss(dev, action, err);
   19859                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   19860         [ #  # ]:          0 :                 if (!priv->sh->aso_age_mng)
   19861                 :          0 :                         return rte_flow_error_set(err, ENOTSUP,
   19862                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   19863                 :            :                                                 NULL,
   19864                 :            :                                                 "Indirect age action not supported");
   19865                 :          0 :                 return flow_dv_validate_action_age(0, action, dev, err);
   19866                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   19867                 :          0 :                 return flow_dv_validate_action_count(dev, true, 0, false, err);
   19868                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   19869         [ #  # ]:          0 :                 if (!priv->sh->ct_aso_en)
   19870                 :          0 :                         return rte_flow_error_set(err, ENOTSUP,
   19871                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19872                 :            :                                         "ASO CT is not supported");
   19873                 :          0 :                 return mlx5_validate_action_ct(dev, action->conf, err);
   19874                 :          0 :         default:
   19875                 :          0 :                 return rte_flow_error_set(err, ENOTSUP,
   19876                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   19877                 :            :                                           NULL,
   19878                 :            :                                           "action type not supported");
   19879                 :            :         }
   19880                 :            : }
   19881                 :            : 
   19882                 :            : /*
   19883                 :            :  * Check if the RSS configurations for colors of a meter policy match
   19884                 :            :  * each other, except the queues.
   19885                 :            :  *
   19886                 :            :  * @param[in] r1
   19887                 :            :  *   Pointer to the first RSS flow action.
   19888                 :            :  * @param[in] r2
   19889                 :            :  *   Pointer to the second RSS flow action.
   19890                 :            :  *
   19891                 :            :  * @return
   19892                 :            :  *   0 on match, 1 on conflict.
   19893                 :            :  */
   19894                 :            : static inline int
   19895                 :          0 : flow_dv_mtr_policy_rss_compare(const struct rte_flow_action_rss *r1,
   19896                 :            :                                const struct rte_flow_action_rss *r2)
   19897                 :            : {
   19898         [ #  # ]:          0 :         if (r1 == NULL || r2 == NULL)
   19899                 :            :                 return 0;
   19900   [ #  #  #  #  :          0 :         if (!(r1->level <= 1 && r2->level <= 1) &&
                   #  # ]
   19901         [ #  # ]:          0 :             !(r1->level > 1 && r2->level > 1))
   19902                 :            :                 return 1;
   19903         [ #  # ]:          0 :         if (r1->func != r2->func)
   19904                 :            :                 return 1;
   19905         [ #  # ]:          0 :         if (r1->types != r2->types &&
   19906         [ #  # ]:          0 :             !((r1->types == 0 || r1->types == RTE_ETH_RSS_IP) &&
   19907         [ #  # ]:          0 :               (r2->types == 0 || r2->types == RTE_ETH_RSS_IP)))
   19908                 :            :                 return 1;
   19909   [ #  #  #  # ]:          0 :         if (r1->key || r2->key) {
   19910         [ #  # ]:          0 :                 const void *key1 = r1->key ? r1->key : rss_hash_default_key;
   19911         [ #  # ]:          0 :                 const void *key2 = r2->key ? r2->key : rss_hash_default_key;
   19912                 :            : 
   19913         [ #  # ]:          0 :                 if (memcmp(key1, key2, MLX5_RSS_HASH_KEY_LEN))
   19914                 :          0 :                         return 1;
   19915                 :            :         }
   19916                 :            :         return 0;
   19917                 :            : }
   19918                 :            : 
   19919                 :            : /**
   19920                 :            :  * Validate the meter hierarchy chain for meter policy.
   19921                 :            :  *
   19922                 :            :  * @param[in] dev
   19923                 :            :  *   Pointer to the Ethernet device structure.
   19924                 :            :  * @param[in] meter_id
   19925                 :            :  *   Meter id.
   19926                 :            :  * @param[in] action_flags
   19927                 :            :  *   Holds the actions detected until now.
   19928                 :            :  * @param[out] is_rss
   19929                 :            :  *   Is RSS or not.
   19930                 :            :  * @param[out] hierarchy_domain
   19931                 :            :  *   The domain bitmap for hierarchy policy.
   19932                 :            :  * @param[out] error
   19933                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19934                 :            :  *   error only.
   19935                 :            :  *
   19936                 :            :  * @return
   19937                 :            :  *   0 on success, otherwise negative errno value with error set.
   19938                 :            :  */
   19939                 :            : static int
   19940                 :          0 : flow_dv_validate_policy_mtr_hierarchy(struct rte_eth_dev *dev,
   19941                 :            :                                   uint32_t meter_id,
   19942                 :            :                                   uint64_t action_flags,
   19943                 :            :                                   bool *is_rss,
   19944                 :            :                                   uint8_t *hierarchy_domain,
   19945                 :            :                                   struct rte_mtr_error *error)
   19946                 :            : {
   19947                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19948                 :            :         struct mlx5_flow_meter_info *fm;
   19949                 :            :         struct mlx5_flow_meter_policy *policy;
   19950                 :            :         uint8_t cnt = 1;
   19951                 :            : 
   19952         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
   19953                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   19954                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   19955                 :            :                                         RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
   19956                 :            :                                         NULL,
   19957                 :            :                                         "Multiple fate actions not supported.");
   19958                 :          0 :         *hierarchy_domain = 0;
   19959                 :          0 :         fm = mlx5_flow_meter_find(priv, meter_id, NULL);
   19960                 :            :         while (true) {
   19961         [ #  # ]:          0 :                 if (!fm)
   19962                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19963                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19964                 :            :                                         "Meter not found in meter hierarchy.");
   19965         [ #  # ]:          0 :                 if (fm->def_policy)
   19966                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19967                 :            :                                         RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19968                 :            :                         "Non termination meter not supported in hierarchy.");
   19969         [ #  # ]:          0 :                 if (!fm->shared)
   19970                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19971                 :            :                                         RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   19972                 :            :                                         "Only shared meter supported in hierarchy.");
   19973                 :          0 :                 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
   19974                 :            :                 MLX5_ASSERT(policy);
   19975                 :            :                 /**
   19976                 :            :                  * Only inherit the supported domains of the first meter in
   19977                 :            :                  * hierarchy.
   19978                 :            :                  * One meter supports at least one domain.
   19979                 :            :                  */
   19980         [ #  # ]:          0 :                 if (!*hierarchy_domain) {
   19981         [ #  # ]:          0 :                         if (policy->transfer)
   19982                 :          0 :                                 *hierarchy_domain |=
   19983                 :            :                                                 MLX5_MTR_DOMAIN_TRANSFER_BIT;
   19984         [ #  # ]:          0 :                         if (policy->ingress)
   19985                 :          0 :                                 *hierarchy_domain |=
   19986                 :            :                                                 MLX5_MTR_DOMAIN_INGRESS_BIT;
   19987         [ #  # ]:          0 :                         if (policy->egress)
   19988                 :          0 :                                 *hierarchy_domain |= MLX5_MTR_DOMAIN_EGRESS_BIT;
   19989                 :            :                 }
   19990         [ #  # ]:          0 :                 if (!policy->is_hierarchy) {
   19991                 :          0 :                         *is_rss = policy->is_rss;
   19992                 :            :                         break;
   19993                 :            :                 }
   19994                 :          0 :                 rte_spinlock_lock(&policy->sl);
   19995                 :          0 :                 fm = mlx5_flow_meter_hierarchy_next_meter(priv, policy, NULL);
   19996                 :            :                 rte_spinlock_unlock(&policy->sl);
   19997         [ #  # ]:          0 :                 if (++cnt >= MLX5_MTR_CHAIN_MAX_NUM)
   19998                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   19999                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
   20000                 :            :                                         "Exceed max hierarchy meter number.");
   20001                 :            :         }
   20002                 :          0 :         return 0;
   20003                 :            : }
   20004                 :            : 
   20005                 :            : /**
   20006                 :            :  * Validate meter policy actions.
   20007                 :            :  * Dispatcher for action type specific validation.
   20008                 :            :  *
   20009                 :            :  * @param[in] dev
   20010                 :            :  *   Pointer to the Ethernet device structure.
   20011                 :            :  * @param[in] action
   20012                 :            :  *   The meter policy action object to validate.
   20013                 :            :  * @param[in] attr
   20014                 :            :  *   Attributes of flow to determine steering domain.
   20015                 :            :  * @param[out] error
   20016                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   20017                 :            :  *   error only.
   20018                 :            :  *
   20019                 :            :  * @return
   20020                 :            :  *   0 on success, otherwise negative errno value.
   20021                 :            :  */
   20022                 :            : static int
   20023                 :          0 : flow_dv_validate_mtr_policy_acts(struct rte_eth_dev *dev,
   20024                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
   20025                 :            :                         struct rte_flow_attr *attr,
   20026                 :            :                         bool *is_rss,
   20027                 :            :                         uint8_t *domain_bitmap,
   20028                 :            :                         uint8_t *policy_mode,
   20029                 :            :                         struct rte_mtr_error *error)
   20030                 :            : {
   20031                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20032                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
   20033                 :            :         const struct rte_flow_action *act;
   20034                 :          0 :         uint64_t action_flags[RTE_COLORS] = {0};
   20035                 :            :         int actions_n;
   20036                 :            :         int i, ret;
   20037                 :            :         struct rte_flow_error flow_err;
   20038                 :          0 :         uint8_t domain_color[RTE_COLORS] = {0};
   20039                 :            :         uint8_t def_domain = MLX5_MTR_ALL_DOMAIN_BIT;
   20040                 :          0 :         uint8_t hierarchy_domain = 0;
   20041                 :            :         const struct rte_flow_action_meter *mtr;
   20042                 :            :         const struct rte_flow_action_meter *next_mtr = NULL;
   20043                 :            :         bool def_green = false;
   20044                 :            :         bool def_yellow = false;
   20045                 :          0 :         const struct rte_flow_action_rss *rss_color[RTE_COLORS] = {NULL};
   20046                 :            :         /* Called from RTE API */
   20047   [ #  #  #  #  :          0 :         bool is_root = !(attr->group || (attr->transfer && priv->fdb_def_rule));
                   #  # ]
   20048                 :            : 
   20049         [ #  # ]:          0 :         if (!dev_conf->dv_esw_en)
   20050                 :            :                 def_domain &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20051                 :          0 :         *domain_bitmap = def_domain;
   20052                 :            :         /* Red color could only support DROP action. */
   20053         [ #  # ]:          0 :         if (!actions[RTE_COLOR_RED] ||
   20054         [ #  # ]:          0 :             actions[RTE_COLOR_RED]->type != RTE_FLOW_ACTION_TYPE_DROP)
   20055                 :          0 :                 return -rte_mtr_error_set(error, ENOTSUP,
   20056                 :            :                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   20057                 :            :                                 NULL, "Red color only supports drop action.");
   20058                 :            :         /*
   20059                 :            :          * Check default policy actions:
   20060                 :            :          * Green / Yellow: no action, Red: drop action
   20061                 :            :          * Either G or Y will trigger default policy actions to be created.
   20062                 :            :          */
   20063         [ #  # ]:          0 :         if (!actions[RTE_COLOR_GREEN] ||
   20064         [ #  # ]:          0 :             actions[RTE_COLOR_GREEN]->type == RTE_FLOW_ACTION_TYPE_END)
   20065                 :            :                 def_green = true;
   20066         [ #  # ]:          0 :         if (!actions[RTE_COLOR_YELLOW] ||
   20067         [ #  # ]:          0 :             actions[RTE_COLOR_YELLOW]->type == RTE_FLOW_ACTION_TYPE_END)
   20068                 :            :                 def_yellow = true;
   20069         [ #  # ]:          0 :         if (def_green && def_yellow) {
   20070                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_DEF;
   20071                 :          0 :                 return 0;
   20072         [ #  # ]:          0 :         } else if (!def_green && def_yellow) {
   20073                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_OG;
   20074         [ #  # ]:          0 :         } else if (def_green && !def_yellow) {
   20075                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_OY;
   20076                 :            :         } else {
   20077                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_ALL;
   20078                 :            :         }
   20079                 :            :         /* Set to empty string in case of NULL pointer access by user. */
   20080                 :          0 :         flow_err.message = "";
   20081         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   20082                 :          0 :                 act = actions[i];
   20083                 :          0 :                 for (action_flags[i] = 0, actions_n = 0;
   20084   [ #  #  #  # ]:          0 :                      act && act->type != RTE_FLOW_ACTION_TYPE_END;
   20085                 :          0 :                      act++) {
   20086         [ #  # ]:          0 :                         if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
   20087                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20088                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20089                 :            :                                           NULL, "too many actions");
   20090   [ #  #  #  #  :          0 :                         switch (act->type) {
          #  #  #  #  #  
                      # ]
   20091                 :          0 :                         case RTE_FLOW_ACTION_TYPE_PORT_ID:
   20092                 :            :                         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   20093         [ #  # ]:          0 :                                 if (!dev_conf->dv_esw_en)
   20094                 :          0 :                                         return -rte_mtr_error_set(error,
   20095                 :            :                                         ENOTSUP,
   20096                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20097                 :            :                                         NULL, "PORT action validate check"
   20098                 :            :                                         " fail for ESW disable");
   20099                 :          0 :                                 ret = flow_dv_validate_action_port_id(dev,
   20100                 :            :                                                 action_flags[i],
   20101                 :            :                                                 act, attr, &flow_err);
   20102         [ #  # ]:          0 :                                 if (ret)
   20103                 :          0 :                                         return -rte_mtr_error_set(error,
   20104                 :            :                                         ENOTSUP,
   20105                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20106         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20107                 :            :                                         flow_err.message :
   20108                 :            :                                         "PORT action validate check fail");
   20109                 :          0 :                                 ++actions_n;
   20110                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_PORT_ID;
   20111                 :          0 :                                 break;
   20112                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MARK:
   20113                 :          0 :                                 ret = flow_dv_validate_action_mark(dev, act,
   20114                 :            :                                                            action_flags[i],
   20115                 :            :                                                            attr, &flow_err);
   20116         [ #  # ]:          0 :                                 if (ret < 0)
   20117                 :          0 :                                         return -rte_mtr_error_set(error,
   20118                 :            :                                         ENOTSUP,
   20119                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20120         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20121                 :            :                                         flow_err.message :
   20122                 :            :                                         "Mark action validate check fail");
   20123         [ #  # ]:          0 :                                 if (dev_conf->dv_xmeta_en !=
   20124                 :            :                                         MLX5_XMETA_MODE_LEGACY)
   20125                 :          0 :                                         return -rte_mtr_error_set(error,
   20126                 :            :                                         ENOTSUP,
   20127                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20128                 :            :                                         NULL, "Extend MARK action is "
   20129                 :            :                                         "not supported. Please try use "
   20130                 :            :                                         "default policy for meter.");
   20131                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_MARK;
   20132                 :          0 :                                 ++actions_n;
   20133                 :          0 :                                 break;
   20134                 :          0 :                         case RTE_FLOW_ACTION_TYPE_SET_TAG:
   20135                 :          0 :                                 ret = flow_dv_validate_action_set_tag(dev,
   20136                 :            :                                                         act, action_flags[i],
   20137                 :            :                                                         attr, &flow_err);
   20138         [ #  # ]:          0 :                                 if (ret)
   20139                 :          0 :                                         return -rte_mtr_error_set(error,
   20140                 :            :                                         ENOTSUP,
   20141                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20142         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20143                 :            :                                         flow_err.message :
   20144                 :            :                                         "Set tag action validate check fail");
   20145                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_SET_TAG;
   20146                 :          0 :                                 ++actions_n;
   20147                 :          0 :                                 break;
   20148                 :          0 :                         case RTE_FLOW_ACTION_TYPE_DROP:
   20149                 :          0 :                                 ret = mlx5_flow_validate_action_drop
   20150                 :            :                                         (dev, false, attr, &flow_err);
   20151         [ #  # ]:          0 :                                 if (ret < 0)
   20152                 :          0 :                                         return -rte_mtr_error_set(error,
   20153                 :            :                                         ENOTSUP,
   20154                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20155         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20156                 :            :                                         flow_err.message :
   20157                 :            :                                         "Drop action validate check fail");
   20158                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_DROP;
   20159                 :          0 :                                 ++actions_n;
   20160                 :          0 :                                 break;
   20161                 :          0 :                         case RTE_FLOW_ACTION_TYPE_QUEUE:
   20162                 :            :                                 /*
   20163                 :            :                                  * Check whether extensive
   20164                 :            :                                  * metadata feature is engaged.
   20165                 :            :                                  */
   20166         [ #  # ]:          0 :                                 if (dev_conf->dv_flow_en &&
   20167         [ #  # ]:          0 :                                     (dev_conf->dv_xmeta_en !=
   20168         [ #  # ]:          0 :                                      MLX5_XMETA_MODE_LEGACY) &&
   20169                 :          0 :                                     mlx5_flow_ext_mreg_supported(dev))
   20170                 :          0 :                                         return -rte_mtr_error_set(error,
   20171                 :            :                                           ENOTSUP,
   20172                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20173                 :            :                                           NULL, "Queue action with meta "
   20174                 :            :                                           "is not supported. Please try use "
   20175                 :            :                                           "default policy for meter.");
   20176                 :          0 :                                 ret = mlx5_flow_validate_action_queue(act,
   20177                 :            :                                                         action_flags[i], dev,
   20178                 :            :                                                         attr, &flow_err);
   20179         [ #  # ]:          0 :                                 if (ret < 0)
   20180                 :          0 :                                         return -rte_mtr_error_set(error,
   20181                 :            :                                           ENOTSUP,
   20182                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20183         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20184                 :            :                                           flow_err.message :
   20185                 :            :                                           "Queue action validate check fail");
   20186                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_QUEUE;
   20187                 :          0 :                                 ++actions_n;
   20188                 :          0 :                                 break;
   20189                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RSS:
   20190         [ #  # ]:          0 :                                 if (dev_conf->dv_flow_en &&
   20191         [ #  # ]:          0 :                                     (dev_conf->dv_xmeta_en !=
   20192         [ #  # ]:          0 :                                      MLX5_XMETA_MODE_LEGACY) &&
   20193                 :          0 :                                     mlx5_flow_ext_mreg_supported(dev))
   20194                 :          0 :                                         return -rte_mtr_error_set(error,
   20195                 :            :                                           ENOTSUP,
   20196                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20197                 :            :                                           NULL, "RSS action with meta "
   20198                 :            :                                           "is not supported. Please try use "
   20199                 :            :                                           "default policy for meter.");
   20200                 :          0 :                                 ret = mlx5_validate_action_rss(dev, act,
   20201                 :            :                                                                &flow_err);
   20202         [ #  # ]:          0 :                                 if (ret < 0)
   20203                 :          0 :                                         return -rte_mtr_error_set(error,
   20204                 :            :                                           ENOTSUP,
   20205                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20206         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20207                 :            :                                           flow_err.message :
   20208                 :            :                                           "RSS action validate check fail");
   20209                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_RSS;
   20210                 :          0 :                                 ++actions_n;
   20211                 :            :                                 /* Either G or Y will set the RSS. */
   20212                 :          0 :                                 rss_color[i] = act->conf;
   20213                 :          0 :                                 break;
   20214                 :          0 :                         case RTE_FLOW_ACTION_TYPE_JUMP:
   20215                 :          0 :                                 ret = flow_dv_validate_action_jump(dev,
   20216                 :            :                                         NULL, act, action_flags[i],
   20217                 :            :                                         attr, true, &flow_err);
   20218         [ #  # ]:          0 :                                 if (ret)
   20219                 :          0 :                                         return -rte_mtr_error_set(error,
   20220                 :            :                                           ENOTSUP,
   20221                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20222         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20223                 :            :                                           flow_err.message :
   20224                 :            :                                           "Jump action validate check fail");
   20225                 :          0 :                                 ++actions_n;
   20226                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_JUMP;
   20227                 :          0 :                                 break;
   20228                 :          0 :                         case RTE_FLOW_ACTION_TYPE_METER:
   20229                 :          0 :                                 mtr = act->conf;
   20230   [ #  #  #  # ]:          0 :                                 if (next_mtr && next_mtr->mtr_id != mtr->mtr_id)
   20231                 :          0 :                                         return -rte_mtr_error_set(error, ENOTSUP,
   20232                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
   20233                 :            :                                                 "Green and Yellow must use the same meter.");
   20234                 :          0 :                                 ret = flow_dv_validate_policy_mtr_hierarchy(dev,
   20235                 :          0 :                                                         mtr->mtr_id,
   20236                 :            :                                                         action_flags[i],
   20237                 :            :                                                         is_rss,
   20238                 :            :                                                         &hierarchy_domain,
   20239                 :            :                                                         error);
   20240         [ #  # ]:          0 :                                 if (ret)
   20241                 :          0 :                                         return ret;
   20242                 :          0 :                                 ++actions_n;
   20243                 :          0 :                                 action_flags[i] |=
   20244                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
   20245                 :            :                                 next_mtr = mtr;
   20246                 :          0 :                                 break;
   20247                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   20248                 :          0 :                                 ret = flow_dv_validate_action_modify_field(dev,
   20249                 :            :                                         action_flags[i], act, attr, is_root, &flow_err);
   20250         [ #  # ]:          0 :                                 if (ret < 0)
   20251                 :          0 :                                         return -rte_mtr_error_set(error,
   20252                 :            :                                           ENOTSUP,
   20253                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20254         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20255                 :            :                                           flow_err.message :
   20256                 :            :                                           "Modify field action validate check fail");
   20257                 :          0 :                                 ++actions_n;
   20258                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   20259                 :          0 :                                 break;
   20260                 :            :                         default:
   20261                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20262                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20263                 :            :                                         NULL,
   20264                 :            :                                         "Doesn't support optional action");
   20265                 :            :                         }
   20266                 :            :                 }
   20267         [ #  # ]:          0 :                 if (action_flags[i] & MLX5_FLOW_ACTION_PORT_ID) {
   20268                 :          0 :                         domain_color[i] = MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20269         [ #  # ]:          0 :                 } else if ((action_flags[i] &
   20270                 :          0 :                           (MLX5_FLOW_ACTION_RSS | MLX5_FLOW_ACTION_QUEUE)) ||
   20271         [ #  # ]:          0 :                           (action_flags[i] & MLX5_FLOW_ACTION_MARK)) {
   20272                 :            :                         /*
   20273                 :            :                          * Only support MLX5_XMETA_MODE_LEGACY
   20274                 :            :                          * so MARK action is only in ingress domain.
   20275                 :            :                          */
   20276                 :          0 :                         domain_color[i] = MLX5_MTR_DOMAIN_INGRESS_BIT;
   20277                 :            :                 } else {
   20278                 :          0 :                         domain_color[i] = def_domain;
   20279         [ #  # ]:          0 :                         if (action_flags[i] &&
   20280         [ #  # ]:          0 :                             !(action_flags[i] & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   20281                 :          0 :                                 domain_color[i] &=
   20282                 :            :                                 ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20283                 :            :                 }
   20284         [ #  # ]:          0 :                 if (action_flags[i] &
   20285                 :            :                     MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
   20286                 :          0 :                         domain_color[i] &= hierarchy_domain;
   20287                 :            :                 /*
   20288                 :            :                  * Non-termination actions only support NIC Tx domain.
   20289                 :            :                  * The adjustion should be skipped when there is no
   20290                 :            :                  * action or only END is provided. The default domains
   20291                 :            :                  * bit-mask is set to find the MIN intersection.
   20292                 :            :                  * The action flags checking should also be skipped.
   20293                 :            :                  */
   20294         [ #  # ]:          0 :                 if ((def_green && i == RTE_COLOR_GREEN) ||
   20295         [ #  # ]:          0 :                     (def_yellow && i == RTE_COLOR_YELLOW))
   20296                 :          0 :                         continue;
   20297                 :            :                 /*
   20298                 :            :                  * Validate the drop action mutual exclusion
   20299                 :            :                  * with other actions. Drop action is mutually-exclusive
   20300                 :            :                  * with any other action, except for Count action.
   20301                 :            :                  */
   20302         [ #  # ]:          0 :                 if ((action_flags[i] & MLX5_FLOW_ACTION_DROP) &&
   20303         [ #  # ]:          0 :                     (action_flags[i] & ~MLX5_FLOW_ACTION_DROP)) {
   20304                 :          0 :                         return -rte_mtr_error_set(error, ENOTSUP,
   20305                 :            :                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   20306                 :            :                                 NULL, "Drop action is mutually-exclusive "
   20307                 :            :                                 "with any other action");
   20308                 :            :                 }
   20309                 :            :                 /* Eswitch has few restrictions on using items and actions */
   20310         [ #  # ]:          0 :                 if (domain_color[i] & MLX5_MTR_DOMAIN_TRANSFER_BIT) {
   20311         [ #  # ]:          0 :                         if (!mlx5_flow_ext_mreg_supported(dev) &&
   20312         [ #  # ]:          0 :                             action_flags[i] & MLX5_FLOW_ACTION_MARK)
   20313                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20314                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20315                 :            :                                         NULL, "unsupported action MARK");
   20316         [ #  # ]:          0 :                         if (action_flags[i] & MLX5_FLOW_ACTION_QUEUE)
   20317                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20318                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20319                 :            :                                         NULL, "unsupported action QUEUE");
   20320         [ #  # ]:          0 :                         if (action_flags[i] & MLX5_FLOW_ACTION_RSS)
   20321                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20322                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20323                 :            :                                         NULL, "unsupported action RSS");
   20324         [ #  # ]:          0 :                         if (!(action_flags[i] & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   20325                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20326                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20327                 :            :                                         NULL, "no fate action is found");
   20328                 :            :                 } else {
   20329   [ #  #  #  # ]:          0 :                         if (!(action_flags[i] & MLX5_FLOW_FATE_ACTIONS) &&
   20330                 :            :                             (domain_color[i] & MLX5_MTR_DOMAIN_INGRESS_BIT)) {
   20331         [ #  # ]:          0 :                                 if ((domain_color[i] &
   20332                 :            :                                      MLX5_MTR_DOMAIN_EGRESS_BIT))
   20333                 :          0 :                                         domain_color[i] =
   20334                 :            :                                                 MLX5_MTR_DOMAIN_EGRESS_BIT;
   20335                 :            :                                 else
   20336                 :          0 :                                         return -rte_mtr_error_set(error,
   20337                 :            :                                                 ENOTSUP,
   20338                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   20339                 :            :                                                 NULL,
   20340                 :            :                                                 "no fate action is found");
   20341                 :            :                         }
   20342                 :            :                 }
   20343                 :            :         }
   20344   [ #  #  #  # ]:          0 :         if (next_mtr && *policy_mode == MLX5_MTR_POLICY_MODE_ALL) {
   20345                 :            :                 uint64_t hierarchy_type_flag =
   20346                 :            :                         MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY | MLX5_FLOW_ACTION_JUMP;
   20347         [ #  # ]:          0 :                 if (!(action_flags[RTE_COLOR_GREEN] & hierarchy_type_flag) ||
   20348         [ #  # ]:          0 :                     !(action_flags[RTE_COLOR_YELLOW] & hierarchy_type_flag))
   20349                 :          0 :                         return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_POLICY,
   20350                 :            :                                                   NULL,
   20351                 :            :                                                   "Unsupported action in meter hierarchy.");
   20352                 :            :         }
   20353                 :            :         /* If both colors have RSS, the attributes should be the same. */
   20354         [ #  # ]:          0 :         if (flow_dv_mtr_policy_rss_compare(rss_color[RTE_COLOR_GREEN],
   20355                 :            :                                            rss_color[RTE_COLOR_YELLOW]))
   20356                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   20357                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20358                 :            :                                           NULL, "policy RSS attr conflict");
   20359   [ #  #  #  # ]:          0 :         if (rss_color[RTE_COLOR_GREEN] || rss_color[RTE_COLOR_YELLOW])
   20360                 :          0 :                 *is_rss = true;
   20361                 :            :         /* "domain_color[C]" is non-zero for each color, default is ALL. */
   20362         [ #  # ]:          0 :         if (!def_green && !def_yellow &&
   20363         [ #  # ]:          0 :             domain_color[RTE_COLOR_GREEN] != domain_color[RTE_COLOR_YELLOW] &&
   20364         [ #  # ]:          0 :             !(action_flags[RTE_COLOR_GREEN] & MLX5_FLOW_ACTION_DROP) &&
   20365         [ #  # ]:          0 :             !(action_flags[RTE_COLOR_YELLOW] & MLX5_FLOW_ACTION_DROP))
   20366                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   20367                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20368                 :            :                                           NULL, "policy domains conflict");
   20369                 :            :         /*
   20370                 :            :          * At least one color policy is listed in the actions, the domains
   20371                 :            :          * to be supported should be the intersection.
   20372                 :            :          */
   20373                 :          0 :         *domain_bitmap = domain_color[RTE_COLOR_GREEN] &
   20374                 :          0 :                          domain_color[RTE_COLOR_YELLOW];
   20375                 :          0 :         return 0;
   20376                 :            : }
   20377                 :            : 
   20378                 :            : static int
   20379                 :          0 : flow_dv_sync_domain(struct rte_eth_dev *dev, uint32_t domains, uint32_t flags)
   20380                 :            : {
   20381                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20382                 :            :         int ret = 0;
   20383                 :            : 
   20384   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_NIC_RX) && priv->sh->rx_domain != NULL) {
   20385                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->rx_domain,
   20386                 :            :                                                 flags);
   20387         [ #  # ]:          0 :                 if (ret != 0)
   20388                 :            :                         return ret;
   20389                 :            :         }
   20390   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_NIC_TX) && priv->sh->tx_domain != NULL) {
   20391                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->tx_domain, flags);
   20392         [ #  # ]:          0 :                 if (ret != 0)
   20393                 :            :                         return ret;
   20394                 :            :         }
   20395   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_FDB) && priv->sh->fdb_domain != NULL) {
   20396                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->fdb_domain, flags);
   20397         [ #  # ]:          0 :                 if (ret != 0)
   20398                 :          0 :                         return ret;
   20399                 :            :         }
   20400                 :            :         return 0;
   20401                 :            : }
   20402                 :            : 
   20403                 :            : /**
   20404                 :            :  * Discover the number of available flow priorities
   20405                 :            :  * by trying to create a flow with the highest priority value
   20406                 :            :  * for each possible number.
   20407                 :            :  *
   20408                 :            :  * @param[in] dev
   20409                 :            :  *   Ethernet device.
   20410                 :            :  * @param[in] vprio
   20411                 :            :  *   List of possible number of available priorities.
   20412                 :            :  * @param[in] vprio_n
   20413                 :            :  *   Size of @p vprio array.
   20414                 :            :  * @return
   20415                 :            :  *   On success, number of available flow priorities.
   20416                 :            :  *   On failure, a negative errno-style code and rte_errno is set.
   20417                 :            :  */
   20418                 :            : static int
   20419                 :          0 : flow_dv_discover_priorities(struct rte_eth_dev *dev,
   20420                 :            :                             const uint16_t *vprio, int vprio_n)
   20421                 :            : {
   20422                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20423                 :          0 :         struct mlx5_indexed_pool *pool = priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW];
   20424                 :            :         struct rte_flow_item_eth eth;
   20425                 :          0 :         struct rte_flow_item item = {
   20426                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   20427                 :            :                 .spec = &eth,
   20428                 :            :                 .mask = &eth,
   20429                 :            :         };
   20430                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   20431                 :            :                 .mask = {
   20432                 :            :                         .size = sizeof(matcher.mask.buf),
   20433                 :            :                 },
   20434                 :            :         };
   20435                 :            :         union mlx5_flow_tbl_key tbl_key;
   20436                 :            :         struct mlx5_flow flow;
   20437                 :            :         void *action;
   20438                 :            :         struct rte_flow_error error;
   20439                 :            :         uint8_t misc_mask;
   20440                 :            :         int i, err, ret = -ENOTSUP;
   20441                 :            : 
   20442                 :            :         /*
   20443                 :            :          * Prepare a flow with a catch-all pattern and a drop action.
   20444                 :            :          * Use drop queue, because shared drop action may be unavailable.
   20445                 :            :          */
   20446                 :          0 :         action = priv->drop_queue.hrxq->action;
   20447         [ #  # ]:          0 :         if (action == NULL) {
   20448                 :          0 :                 DRV_LOG(ERR, "Priority discovery requires a drop action");
   20449                 :          0 :                 rte_errno = ENOTSUP;
   20450                 :          0 :                 return -rte_errno;
   20451                 :            :         }
   20452                 :            :         memset(&flow, 0, sizeof(flow));
   20453                 :          0 :         flow.handle = mlx5_ipool_zmalloc(pool, &flow.handle_idx);
   20454         [ #  # ]:          0 :         if (flow.handle == NULL) {
   20455                 :          0 :                 DRV_LOG(ERR, "Cannot create flow handle");
   20456                 :          0 :                 rte_errno = ENOMEM;
   20457                 :          0 :                 return -rte_errno;
   20458                 :            :         }
   20459                 :          0 :         flow.ingress = true;
   20460                 :          0 :         flow.dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);
   20461                 :          0 :         flow.dv.actions[0] = action;
   20462                 :          0 :         flow.dv.actions_n = 1;
   20463                 :            :         memset(&eth, 0, sizeof(eth));
   20464                 :          0 :         flow_dv_translate_item_eth(matcher.mask.buf, &item,
   20465                 :            :                                    /* inner */ false, /* group */ 0,
   20466                 :            :                                    MLX5_SET_MATCHER_SW_M);
   20467                 :          0 :         flow_dv_translate_item_eth(flow.dv.value.buf, &item,
   20468                 :            :                                    /* inner */ false, /* group */ 0,
   20469                 :            :                                    MLX5_SET_MATCHER_SW_V);
   20470                 :          0 :         matcher.crc = rte_raw_cksum(matcher.mask.buf, matcher.mask.size);
   20471         [ #  # ]:          0 :         for (i = 0; i < vprio_n; i++) {
   20472                 :            :                 /* Configure the next proposed maximum priority. */
   20473                 :          0 :                 matcher.priority = vprio[i] - 1;
   20474                 :            :                 memset(&tbl_key, 0, sizeof(tbl_key));
   20475                 :          0 :                 err = flow_dv_matcher_register(dev, &matcher, &tbl_key, &flow,
   20476                 :            :                                                /* tunnel */ NULL,
   20477                 :            :                                                /* group */ 0,
   20478                 :            :                                                &error);
   20479         [ #  # ]:          0 :                 if (err != 0) {
   20480                 :            :                         /* This action is pure SW and must always succeed. */
   20481                 :          0 :                         DRV_LOG(ERR, "Cannot register matcher");
   20482                 :          0 :                         ret = -rte_errno;
   20483                 :          0 :                         break;
   20484                 :            :                 }
   20485                 :            :                 /* Try to apply the flow to HW. */
   20486         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(flow.handle->dvh.matcher->mask.buf);
   20487                 :            :                 __flow_dv_adjust_buf_size(&flow.dv.value.size, misc_mask);
   20488                 :          0 :                 err = mlx5_flow_os_create_flow
   20489                 :            :                                 (flow.handle->dvh.matcher->matcher_object,
   20490                 :          0 :                                  (void *)&flow.dv.value, flow.dv.actions_n,
   20491                 :            :                                  flow.dv.actions, &flow.handle->drv_flow);
   20492                 :            :                 if (err == 0) {
   20493                 :          0 :                         claim_zero(mlx5_flow_os_destroy_flow
   20494                 :            :                                                 (flow.handle->drv_flow));
   20495                 :          0 :                         flow.handle->drv_flow = NULL;
   20496                 :            :                 }
   20497                 :          0 :                 claim_zero(flow_dv_matcher_release(dev, flow.handle));
   20498         [ #  # ]:          0 :                 if (err != 0)
   20499                 :            :                         break;
   20500                 :          0 :                 ret = vprio[i];
   20501                 :            :         }
   20502                 :          0 :         mlx5_ipool_free(pool, flow.handle_idx);
   20503                 :            :         /* Set rte_errno if no expected priority value matched. */
   20504         [ #  # ]:          0 :         if (ret < 0)
   20505                 :          0 :                 rte_errno = -ret;
   20506                 :            :         return ret;
   20507                 :            : }
   20508                 :            : 
   20509                 :            : const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
   20510                 :            :         .list_create = flow_legacy_list_create,
   20511                 :            :         .list_destroy = flow_legacy_list_destroy,
   20512                 :            :         .validate = flow_dv_validate,
   20513                 :            :         .prepare = flow_dv_prepare,
   20514                 :            :         .translate = flow_dv_translate,
   20515                 :            :         .apply = flow_dv_apply,
   20516                 :            :         .remove = flow_dv_remove,
   20517                 :            :         .destroy = flow_dv_destroy,
   20518                 :            :         .query = flow_dv_query,
   20519                 :            :         .create_mtr_tbls = flow_dv_create_mtr_tbls,
   20520                 :            :         .destroy_mtr_tbls = flow_dv_destroy_mtr_tbls,
   20521                 :            :         .destroy_mtr_drop_tbls = flow_dv_destroy_mtr_drop_tbls,
   20522                 :            :         .create_meter = flow_dv_mtr_alloc,
   20523                 :            :         .free_meter = flow_dv_aso_mtr_release_to_pool,
   20524                 :            :         .validate_mtr_acts = flow_dv_validate_mtr_policy_acts,
   20525                 :            :         .create_mtr_acts = flow_dv_create_mtr_policy_acts,
   20526                 :            :         .destroy_mtr_acts = flow_dv_destroy_mtr_policy_acts,
   20527                 :            :         .create_policy_rules = flow_dv_create_policy_rules,
   20528                 :            :         .destroy_policy_rules = flow_dv_destroy_policy_rules,
   20529                 :            :         .create_def_policy = flow_dv_create_def_policy,
   20530                 :            :         .destroy_def_policy = flow_dv_destroy_def_policy,
   20531                 :            :         .meter_sub_policy_rss_prepare = flow_dv_meter_sub_policy_rss_prepare,
   20532                 :            :         .meter_hierarchy_rule_create = flow_dv_meter_hierarchy_rule_create,
   20533                 :            :         .destroy_sub_policy_with_rxq = flow_dv_destroy_sub_policy_with_rxq,
   20534                 :            :         .counter_alloc = flow_dv_counter_allocate,
   20535                 :            :         .counter_free = flow_dv_counter_free,
   20536                 :            :         .counter_query = flow_dv_counter_query,
   20537                 :            :         .get_aged_flows = flow_dv_get_aged_flows,
   20538                 :            :         .action_validate = flow_dv_action_validate,
   20539                 :            :         .action_create = flow_dv_action_create,
   20540                 :            :         .action_destroy = flow_dv_action_destroy,
   20541                 :            :         .action_update = flow_dv_action_update,
   20542                 :            :         .action_query = flow_dv_action_query,
   20543                 :            :         .sync_domain = flow_dv_sync_domain,
   20544                 :            :         .discover_priorities = flow_dv_discover_priorities,
   20545                 :            :         .item_create = flow_dv_item_create,
   20546                 :            :         .item_release = flow_dv_item_release,
   20547                 :            : };
   20548                 :            : 
   20549                 :            : #endif /* HAVE_IBV_FLOW_DV_SUPPORT */

Generated by: LCOV version 1.14