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 7641 0.0 %
Date: 2026-04-01 20:02:27 Functions: 0 291 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 6157 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                 :            :  * mlx5_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                 :            : static 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                 :            : static 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                 :            : static 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                 :            : static 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                 :            : static struct field_modify_info modify_ipv6_traffic_class[] = {
     257                 :            :         {1,  0, MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS},
     258                 :            :         {0, 0, 0},
     259                 :            : };
     260                 :            : 
     261                 :            : static 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                 :            : static 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 : mlx5_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 mlx5_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 mlx5_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 mlx5_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 mlx5_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 mlx5_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 mlx5_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 mlx5_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 mlx5_flow_dv_convert_modify_action(&item, modify_tcp, NULL, resource,
     988                 :            :                                                   MLX5_MODIFICATION_TYPE_ADD, error);
     989                 :            : }
     990                 :            : 
     991                 :            : enum mlx5_modification_field mlx5_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(mlx5_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(mlx5_reg_to_field));
    1040                 :          0 :         actions[i] = (struct mlx5_modification_cmd) {
    1041                 :            :                 .action_type = MLX5_MODIFICATION_TYPE_SET,
    1042                 :          0 :                 .field = mlx5_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         [ #  # ]:          0 :         if ((unsigned int)ret >= RTE_DIM(mlx5_reg_to_field))
    1092                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1093                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1094                 :            :                                           NULL, "invalid register index");
    1095                 :          0 :         reg_type = mlx5_reg_to_field[ret];
    1096                 :            :         MLX5_ASSERT(reg_type > 0);
    1097                 :          0 :         reg_c_x[0] = (struct field_modify_info){4, 0, reg_type};
    1098                 :          0 :         return mlx5_flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource,
    1099                 :            :                                                   MLX5_MODIFICATION_TYPE_SET, error);
    1100                 :            : }
    1101                 :            : 
    1102                 :            : /**
    1103                 :            :  * Convert internal COPY_REG action to DV specification.
    1104                 :            :  *
    1105                 :            :  * @param[in] dev
    1106                 :            :  *   Pointer to the rte_eth_dev structure.
    1107                 :            :  * @param[in,out] res
    1108                 :            :  *   Pointer to the modify-header resource.
    1109                 :            :  * @param[in] action
    1110                 :            :  *   Pointer to action specification.
    1111                 :            :  * @param[out] error
    1112                 :            :  *   Pointer to the error structure.
    1113                 :            :  *
    1114                 :            :  * @return
    1115                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1116                 :            :  */
    1117                 :            : static int
    1118                 :          0 : flow_dv_convert_action_copy_mreg(struct rte_eth_dev *dev,
    1119                 :            :                                  struct mlx5_flow_dv_modify_hdr_resource *res,
    1120                 :            :                                  const struct rte_flow_action *action,
    1121                 :            :                                  struct rte_flow_error *error)
    1122                 :            : {
    1123                 :          0 :         const struct mlx5_flow_action_copy_mreg *conf = action->conf;
    1124                 :          0 :         rte_be32_t mask = RTE_BE32(UINT32_MAX);
    1125                 :          0 :         struct rte_flow_item item = {
    1126                 :            :                 .spec = NULL,
    1127                 :            :                 .mask = &mask,
    1128                 :            :         };
    1129                 :          0 :         struct field_modify_info reg_src[] = {
    1130                 :          0 :                 {4, 0, mlx5_reg_to_field[conf->src]},
    1131                 :            :                 {0, 0, 0},
    1132                 :            :         };
    1133                 :          0 :         struct field_modify_info reg_dst = {
    1134                 :            :                 .offset = 0,
    1135                 :          0 :                 .id = mlx5_reg_to_field[conf->dst],
    1136                 :            :         };
    1137                 :            :         /* Adjust reg_c[0] usage according to reported mask. */
    1138   [ #  #  #  # ]:          0 :         if (conf->dst == REG_C_0 || conf->src == REG_C_0) {
    1139                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    1140                 :          0 :                 uint32_t reg_c0 = priv->sh->dv_regc0_mask;
    1141                 :            : 
    1142                 :            :                 MLX5_ASSERT(reg_c0);
    1143                 :            :                 MLX5_ASSERT(priv->sh->config.dv_xmeta_en !=
    1144                 :            :                             MLX5_XMETA_MODE_LEGACY);
    1145         [ #  # ]:          0 :                 if (conf->dst == REG_C_0) {
    1146                 :            :                         /* Copy to reg_c[0], within mask only. */
    1147                 :          0 :                         reg_dst.offset = rte_bsf32(reg_c0);
    1148         [ #  # ]:          0 :                         mask = rte_cpu_to_be_32(reg_c0 >> reg_dst.offset);
    1149                 :            :                 } else {
    1150                 :            :                         reg_dst.offset = 0;
    1151         [ #  # ]:          0 :                         mask = rte_cpu_to_be_32(reg_c0);
    1152                 :            :                 }
    1153                 :            :         }
    1154                 :          0 :         return mlx5_flow_dv_convert_modify_action(&item,
    1155                 :            :                                                   reg_src, &reg_dst, res,
    1156                 :            :                                                   MLX5_MODIFICATION_TYPE_COPY,
    1157                 :            :                                                   error);
    1158                 :            : }
    1159                 :            : 
    1160                 :            : /**
    1161                 :            :  * Convert MARK action to DV specification. This routine is used
    1162                 :            :  * in extensive metadata only and requires metadata register to be
    1163                 :            :  * handled. In legacy mode hardware tag resource is engaged.
    1164                 :            :  *
    1165                 :            :  * @param[in] dev
    1166                 :            :  *   Pointer to the rte_eth_dev structure.
    1167                 :            :  * @param[in] conf
    1168                 :            :  *   Pointer to MARK action specification.
    1169                 :            :  * @param[in,out] resource
    1170                 :            :  *   Pointer to the modify-header resource.
    1171                 :            :  * @param[out] error
    1172                 :            :  *   Pointer to the error structure.
    1173                 :            :  *
    1174                 :            :  * @return
    1175                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1176                 :            :  */
    1177                 :            : static int
    1178                 :          0 : flow_dv_convert_action_mark(struct rte_eth_dev *dev,
    1179                 :            :                             const struct rte_flow_action_mark *conf,
    1180                 :            :                             struct mlx5_flow_dv_modify_hdr_resource *resource,
    1181                 :            :                             struct rte_flow_error *error)
    1182                 :            : {
    1183                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1184         [ #  # ]:          0 :         rte_be32_t mask = rte_cpu_to_be_32(MLX5_FLOW_MARK_MASK &
    1185                 :            :                                            priv->sh->dv_mark_mask);
    1186         [ #  # ]:          0 :         rte_be32_t data = rte_cpu_to_be_32(conf->id) & mask;
    1187                 :          0 :         struct rte_flow_item item = {
    1188                 :            :                 .spec = &data,
    1189                 :            :                 .mask = &mask,
    1190                 :            :         };
    1191                 :          0 :         struct field_modify_info reg_c_x[] = {
    1192                 :            :                 [1] = {0, 0, 0},
    1193                 :            :         };
    1194                 :            :         int reg;
    1195                 :            : 
    1196         [ #  # ]:          0 :         if (!mask)
    1197                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1198                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    1199                 :            :                                           NULL, "zero mark action mask");
    1200                 :          0 :         reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    1201         [ #  # ]:          0 :         if (reg < 0)
    1202                 :            :                 return reg;
    1203                 :            :         MLX5_ASSERT(reg > 0);
    1204         [ #  # ]:          0 :         if (reg == REG_C_0) {
    1205         [ #  # ]:          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
    1206                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
    1207                 :            : 
    1208         [ #  # ]:          0 :                 data = rte_cpu_to_be_32(rte_cpu_to_be_32(data) << shl_c0);
    1209         [ #  # ]:          0 :                 mask = rte_cpu_to_be_32(mask) & msk_c0;
    1210         [ #  # ]:          0 :                 mask = rte_cpu_to_be_32(mask << shl_c0);
    1211                 :            :         }
    1212                 :          0 :         reg_c_x[0] = (struct field_modify_info){4, 0, mlx5_reg_to_field[reg]};
    1213                 :          0 :         return mlx5_flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource,
    1214                 :            :                                                   MLX5_MODIFICATION_TYPE_SET, error);
    1215                 :            : }
    1216                 :            : 
    1217                 :            : /**
    1218                 :            :  * Get metadata register index for specified steering domain.
    1219                 :            :  *
    1220                 :            :  * @param[in] dev
    1221                 :            :  *   Pointer to the rte_eth_dev structure.
    1222                 :            :  * @param[in] attr
    1223                 :            :  *   Attributes of flow to determine steering domain.
    1224                 :            :  * @param[out] error
    1225                 :            :  *   Pointer to the error structure.
    1226                 :            :  *
    1227                 :            :  * @return
    1228                 :            :  *   positive index on success, a negative errno value otherwise
    1229                 :            :  *   and rte_errno is set.
    1230                 :            :  */
    1231                 :            : static enum modify_reg
    1232                 :          0 : flow_dv_get_metadata_reg(struct rte_eth_dev *dev,
    1233                 :            :                          const struct rte_flow_attr *attr,
    1234                 :            :                          struct rte_flow_error *error)
    1235                 :            : {
    1236                 :            :         int reg =
    1237         [ #  # ]:          0 :                 mlx5_flow_get_reg_id(dev, attr->transfer ?
    1238                 :          0 :                                           MLX5_METADATA_FDB :
    1239         [ #  # ]:          0 :                                             attr->egress ?
    1240                 :            :                                             MLX5_METADATA_TX :
    1241                 :            :                                             MLX5_METADATA_RX, 0, error);
    1242         [ #  # ]:          0 :         if (reg < 0)
    1243                 :          0 :                 return rte_flow_error_set(error,
    1244                 :            :                                           ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
    1245                 :            :                                           NULL, "unavailable "
    1246                 :            :                                           "metadata register");
    1247                 :          0 :         return reg;
    1248                 :            : }
    1249                 :            : 
    1250                 :            : /**
    1251                 :            :  * Convert SET_META action to DV specification.
    1252                 :            :  *
    1253                 :            :  * @param[in] dev
    1254                 :            :  *   Pointer to the rte_eth_dev structure.
    1255                 :            :  * @param[in,out] resource
    1256                 :            :  *   Pointer to the modify-header resource.
    1257                 :            :  * @param[in] attr
    1258                 :            :  *   Attributes of flow that includes this item.
    1259                 :            :  * @param[in] conf
    1260                 :            :  *   Pointer to action specification.
    1261                 :            :  * @param[out] error
    1262                 :            :  *   Pointer to the error structure.
    1263                 :            :  *
    1264                 :            :  * @return
    1265                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1266                 :            :  */
    1267                 :            : static int
    1268                 :          0 : flow_dv_convert_action_set_meta
    1269                 :            :                         (struct rte_eth_dev *dev,
    1270                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    1271                 :            :                          const struct rte_flow_attr *attr,
    1272                 :            :                          const struct rte_flow_action_set_meta *conf,
    1273                 :            :                          struct rte_flow_error *error)
    1274                 :            : {
    1275         [ #  # ]:          0 :         uint32_t mask = rte_cpu_to_be_32(conf->mask);
    1276         [ #  # ]:          0 :         uint32_t data = rte_cpu_to_be_32(conf->data) & mask;
    1277                 :          0 :         struct rte_flow_item item = {
    1278                 :            :                 .spec = &data,
    1279                 :            :                 .mask = &mask,
    1280                 :            :         };
    1281                 :          0 :         struct field_modify_info reg_c_x[] = {
    1282                 :            :                 [1] = {0, 0, 0},
    1283                 :            :         };
    1284                 :          0 :         int reg = flow_dv_get_metadata_reg(dev, attr, error);
    1285                 :            : 
    1286         [ #  # ]:          0 :         if (reg < 0)
    1287                 :            :                 return reg;
    1288                 :            :         MLX5_ASSERT(reg != REG_NON);
    1289         [ #  # ]:          0 :         if (reg == REG_C_0) {
    1290                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    1291         [ #  # ]:          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
    1292                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
    1293                 :            : 
    1294         [ #  # ]:          0 :                 data = rte_cpu_to_be_32(rte_cpu_to_be_32(data) << shl_c0);
    1295         [ #  # ]:          0 :                 mask = rte_cpu_to_be_32(mask) & msk_c0;
    1296         [ #  # ]:          0 :                 mask = rte_cpu_to_be_32(mask << shl_c0);
    1297                 :            :         }
    1298                 :          0 :         reg_c_x[0] = (struct field_modify_info){4, 0, mlx5_reg_to_field[reg]};
    1299                 :            :         /* The routine expects parameters in memory as big-endian ones. */
    1300                 :          0 :         return mlx5_flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource,
    1301                 :            :                                                   MLX5_MODIFICATION_TYPE_SET, error);
    1302                 :            : }
    1303                 :            : 
    1304                 :            : /**
    1305                 :            :  * Convert modify-header set IPv4 DSCP action to DV specification.
    1306                 :            :  *
    1307                 :            :  * @param[in,out] resource
    1308                 :            :  *   Pointer to the modify-header resource.
    1309                 :            :  * @param[in] action
    1310                 :            :  *   Pointer to action specification.
    1311                 :            :  * @param[out] error
    1312                 :            :  *   Pointer to the error structure.
    1313                 :            :  *
    1314                 :            :  * @return
    1315                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1316                 :            :  */
    1317                 :            : static int
    1318                 :          0 : flow_dv_convert_action_modify_ipv4_dscp
    1319                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
    1320                 :            :                          const struct rte_flow_action *action,
    1321                 :            :                          struct rte_flow_error *error)
    1322                 :            : {
    1323                 :          0 :         const struct rte_flow_action_set_dscp *conf =
    1324                 :            :                 (const struct rte_flow_action_set_dscp *)(action->conf);
    1325                 :          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV4 };
    1326                 :            :         struct rte_flow_item_ipv4 ipv4;
    1327                 :            :         struct rte_flow_item_ipv4 ipv4_mask;
    1328                 :            : 
    1329                 :            :         memset(&ipv4, 0, sizeof(ipv4));
    1330                 :            :         memset(&ipv4_mask, 0, sizeof(ipv4_mask));
    1331                 :          0 :         ipv4.hdr.type_of_service = conf->dscp;
    1332                 :          0 :         ipv4_mask.hdr.type_of_service = RTE_IPV4_HDR_DSCP_MASK >> 2;
    1333                 :          0 :         item.spec = &ipv4;
    1334                 :          0 :         item.mask = &ipv4_mask;
    1335                 :          0 :         return mlx5_flow_dv_convert_modify_action(&item, modify_ipv4, NULL, resource,
    1336                 :            :                                                   MLX5_MODIFICATION_TYPE_SET, error);
    1337                 :            : }
    1338                 :            : 
    1339                 :            : /**
    1340                 :            :  * Convert modify-header set IPv6 DSCP action to DV specification.
    1341                 :            :  *
    1342                 :            :  * @param[in,out] resource
    1343                 :            :  *   Pointer to the modify-header resource.
    1344                 :            :  * @param[in] action
    1345                 :            :  *   Pointer to action specification.
    1346                 :            :  * @param[out] error
    1347                 :            :  *   Pointer to the error structure.
    1348                 :            :  *
    1349                 :            :  * @return
    1350                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1351                 :            :  */
    1352                 :            : static int
    1353                 :          0 : flow_dv_convert_action_modify_ipv6_dscp
    1354                 :            :                         (struct mlx5_flow_dv_modify_hdr_resource *resource,
    1355                 :            :                          const struct rte_flow_action *action,
    1356                 :            :                          uint32_t ipv6_tc_off,
    1357                 :            :                          struct rte_flow_error *error)
    1358                 :            : {
    1359                 :          0 :         const struct rte_flow_action_set_dscp *conf =
    1360                 :            :                 (const struct rte_flow_action_set_dscp *)(action->conf);
    1361         [ #  # ]:          0 :         struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV6 };
    1362                 :            :         struct rte_flow_item_ipv6 ipv6;
    1363                 :            :         struct rte_flow_item_ipv6 ipv6_mask;
    1364                 :            :         struct field_modify_info *modify_info;
    1365                 :            : 
    1366                 :            :         memset(&ipv6, 0, sizeof(ipv6));
    1367                 :            :         memset(&ipv6_mask, 0, sizeof(ipv6_mask));
    1368                 :            :         /*
    1369                 :            :          * Even though the DSCP bits offset of IPv6 is not byte aligned,
    1370                 :            :          * rdma-core only accept the DSCP bits byte aligned start from
    1371                 :            :          * bit 0 to 5 as to be compatible with IPv4. No need to shift the
    1372                 :            :          * bits in IPv6 case as rdma-core requires byte aligned value.
    1373                 :            :          * IPv6 DSCP uses OUT_IPV6_TRAFFIC_CLASS as ID but it starts from 2
    1374                 :            :          * bits left. Shift the mask left for IPv6 DSCP. Do it here because
    1375                 :            :          * it's needed to distinguish DSCP from ECN in data field construct
    1376                 :            :          */
    1377                 :          0 :         ipv6.hdr.vtc_flow = conf->dscp << ipv6_tc_off;
    1378                 :          0 :         ipv6_mask.hdr.vtc_flow = RTE_IPV6_HDR_DSCP_MASK >> (22 - ipv6_tc_off);
    1379                 :          0 :         item.spec = &ipv6;
    1380                 :          0 :         item.mask = &ipv6_mask;
    1381         [ #  # ]:          0 :         if (ipv6_tc_off)
    1382                 :            :                 modify_info = modify_ipv6_traffic_class;
    1383                 :            :         else
    1384                 :            :                 modify_info = modify_ipv6;
    1385                 :          0 :         return mlx5_flow_dv_convert_modify_action(&item, modify_info, NULL, resource,
    1386                 :            :                                                   MLX5_MODIFICATION_TYPE_SET, error);
    1387                 :            : }
    1388                 :            : 
    1389                 :            : int
    1390                 :          0 : mlx5_flow_item_field_width(struct rte_eth_dev *dev,
    1391                 :            :                            enum rte_flow_field_id field, int inherit,
    1392                 :            :                            const struct rte_flow_attr *attr,
    1393                 :            :                            struct rte_flow_error *error)
    1394                 :            : {
    1395                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1396                 :            : 
    1397   [ #  #  #  #  :          0 :         switch (field) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1398                 :            :         case RTE_FLOW_FIELD_START:
    1399                 :            :                 return 32;
    1400                 :          0 :         case RTE_FLOW_FIELD_MAC_DST:
    1401                 :            :         case RTE_FLOW_FIELD_MAC_SRC:
    1402                 :          0 :                 return 48;
    1403                 :          0 :         case RTE_FLOW_FIELD_VLAN_TYPE:
    1404                 :          0 :                 return 16;
    1405                 :          0 :         case RTE_FLOW_FIELD_VLAN_ID:
    1406                 :          0 :                 return 12;
    1407                 :          0 :         case RTE_FLOW_FIELD_MAC_TYPE:
    1408                 :          0 :                 return 16;
    1409                 :          0 :         case RTE_FLOW_FIELD_IPV4_DSCP:
    1410                 :          0 :                 return 6;
    1411                 :          0 :         case RTE_FLOW_FIELD_IPV4_TTL:
    1412                 :            :         case RTE_FLOW_FIELD_IPV4_PROTO:
    1413                 :          0 :                 return 8;
    1414                 :            :         case RTE_FLOW_FIELD_IPV4_SRC:
    1415                 :            :         case RTE_FLOW_FIELD_IPV4_DST:
    1416                 :            :                 return 32;
    1417                 :          0 :         case RTE_FLOW_FIELD_IPV6_DSCP:
    1418                 :          0 :                 return 6;
    1419                 :          0 :         case RTE_FLOW_FIELD_IPV6_FLOW_LABEL:
    1420                 :          0 :                 return 20;
    1421                 :          0 :         case RTE_FLOW_FIELD_IPV6_TRAFFIC_CLASS:
    1422                 :            :         case RTE_FLOW_FIELD_IPV6_HOPLIMIT:
    1423                 :            :         case RTE_FLOW_FIELD_IPV6_PROTO:
    1424                 :          0 :                 return 8;
    1425                 :          0 :         case RTE_FLOW_FIELD_IPV6_SRC:
    1426                 :            :         case RTE_FLOW_FIELD_IPV6_DST:
    1427                 :          0 :                 return 128;
    1428                 :          0 :         case RTE_FLOW_FIELD_TCP_PORT_SRC:
    1429                 :            :         case RTE_FLOW_FIELD_TCP_PORT_DST:
    1430                 :          0 :                 return 16;
    1431                 :            :         case RTE_FLOW_FIELD_TCP_SEQ_NUM:
    1432                 :            :         case RTE_FLOW_FIELD_TCP_ACK_NUM:
    1433                 :            :                 return 32;
    1434                 :          0 :         case RTE_FLOW_FIELD_TCP_FLAGS:
    1435                 :          0 :                 return 9;
    1436                 :          0 :         case RTE_FLOW_FIELD_UDP_PORT_SRC:
    1437                 :            :         case RTE_FLOW_FIELD_UDP_PORT_DST:
    1438                 :          0 :                 return 16;
    1439                 :          0 :         case RTE_FLOW_FIELD_VXLAN_VNI:
    1440                 :            :         case RTE_FLOW_FIELD_GENEVE_VNI:
    1441                 :          0 :                 return 24;
    1442                 :          0 :         case RTE_FLOW_FIELD_VXLAN_LAST_RSVD:
    1443                 :          0 :                 return 8;
    1444                 :            :         case RTE_FLOW_FIELD_GTP_TEID:
    1445                 :            :         case RTE_FLOW_FIELD_MPLS:
    1446                 :            :         case RTE_FLOW_FIELD_TAG:
    1447                 :            :         case RTE_FLOW_FIELD_ESP_SPI:
    1448                 :            :         case RTE_FLOW_FIELD_ESP_SEQ_NUM:
    1449                 :            :                 return 32;
    1450                 :          0 :         case RTE_FLOW_FIELD_ESP_PROTO:
    1451                 :          0 :                 return 8;
    1452                 :          0 :         case RTE_FLOW_FIELD_MARK:
    1453                 :          0 :                 return rte_popcount32(priv->sh->dv_mark_mask);
    1454                 :          0 :         case RTE_FLOW_FIELD_META:
    1455                 :          0 :                 return (flow_dv_get_metadata_reg(dev, attr, error) == REG_C_0) ?
    1456         [ #  # ]:          0 :                         rte_popcount32(priv->sh->dv_meta_mask) : 32;
    1457                 :          0 :         case RTE_FLOW_FIELD_GTP_PSC_QFI:
    1458                 :          0 :                 return 6;
    1459                 :          0 :         case RTE_FLOW_FIELD_POINTER:
    1460                 :            :         case RTE_FLOW_FIELD_VALUE:
    1461                 :          0 :                 return inherit < 0 ? 0 : inherit;
    1462                 :          0 :         case RTE_FLOW_FIELD_IPV4_ECN:
    1463                 :            :         case RTE_FLOW_FIELD_IPV6_ECN:
    1464                 :            :         case RTE_FLOW_FIELD_METER_COLOR:
    1465                 :          0 :                 return 2;
    1466                 :            :         case RTE_FLOW_FIELD_HASH_RESULT:
    1467                 :            :                 return 32;
    1468                 :          0 :         default:
    1469                 :            :                 MLX5_ASSERT(false);
    1470                 :            :         }
    1471                 :          0 :         return 0;
    1472                 :            : }
    1473                 :            : 
    1474                 :            : static __rte_always_inline uint8_t
    1475                 :            : flow_modify_info_mask_8(uint32_t length, uint32_t off)
    1476                 :            : {
    1477                 :          0 :         return (0xffu >> (8 - length)) << off;
    1478                 :            : }
    1479                 :            : 
    1480                 :            : static __rte_always_inline uint16_t
    1481                 :            : flow_modify_info_mask_16(uint32_t length, uint32_t off)
    1482                 :            : {
    1483   [ #  #  #  #  :          0 :         return rte_cpu_to_be_16((0xffffu >> (16 - length)) << off);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1484                 :            : }
    1485                 :            : 
    1486                 :            : static __rte_always_inline uint32_t
    1487                 :            : flow_modify_info_mask_32(uint32_t length, uint32_t off)
    1488                 :            : {
    1489   [ #  #  #  #  :          0 :         return rte_cpu_to_be_32((0xffffffffu >> (32 - length)) << off);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1490                 :            : }
    1491                 :            : 
    1492                 :            : static __rte_always_inline uint32_t
    1493                 :            : flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mask)
    1494                 :            : {
    1495                 :          0 :         uint32_t mask = (0xffffffffu >> (32 - length)) << off;
    1496                 :          0 :         return rte_cpu_to_be_32(mask & post_mask);
    1497                 :            : }
    1498                 :            : 
    1499                 :            : static __rte_always_inline enum mlx5_modification_field
    1500                 :            : mlx5_mpls_modi_field_get(const struct rte_flow_field_data *data)
    1501                 :            : {
    1502                 :          0 :         return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index;
    1503                 :            : }
    1504                 :            : 
    1505                 :            : static __rte_always_inline int
    1506                 :            : flow_geneve_opt_modi_field_get(struct mlx5_priv *priv,
    1507                 :            :                                const struct rte_flow_field_data *data)
    1508                 :            : {
    1509                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    1510                 :          0 :         return mlx5_geneve_opt_modi_field_get(priv, data);
    1511                 :            : #else
    1512                 :            :         (void)priv;
    1513                 :            :         (void)data;
    1514                 :            :         DRV_LOG(ERR, "GENEVE option modification is not supported.");
    1515                 :            :         rte_errno = ENOTSUP;
    1516                 :            :         return -rte_errno;
    1517                 :            : #endif
    1518                 :            : }
    1519                 :            : 
    1520                 :            : static void
    1521                 :          0 : mlx5_modify_flex_item(const struct rte_eth_dev *dev,
    1522                 :            :                       const struct mlx5_flex_item *flex,
    1523                 :            :                       const struct rte_flow_field_data *data,
    1524                 :            :                       struct field_modify_info *info,
    1525                 :            :                       uint32_t *mask, uint32_t width)
    1526                 :            : {
    1527                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1528                 :          0 :         struct mlx5_hca_flex_attr *attr = &priv->sh->cdev->config.hca_attr.flex;
    1529                 :            :         uint32_t i, j;
    1530                 :            :         int id = 0;
    1531                 :          0 :         uint32_t pos = 0;
    1532                 :            :         const struct mlx5_flex_pattern_field *map;
    1533                 :          0 :         uint32_t offset = data->offset;
    1534                 :            :         uint32_t width_left = width;
    1535                 :            :         uint32_t cur_width = 0;
    1536                 :            :         uint32_t tmp_ofs;
    1537                 :            :         uint32_t idx = 0;
    1538                 :            :         struct field_modify_info tmp;
    1539                 :            :         int tmp_id;
    1540                 :            : 
    1541         [ #  # ]:          0 :         if (!attr->query_match_sample_info) {
    1542                 :          0 :                 DRV_LOG(ERR, "FW doesn't support modify field with flex item.");
    1543                 :          0 :                 return;
    1544                 :            :         }
    1545                 :            :         /*
    1546                 :            :          * search for the mapping instance until Accumulated width is no
    1547                 :            :          * less than data->offset.
    1548                 :            :          */
    1549         [ #  # ]:          0 :         for (i = 0; i < flex->mapnum; i++) {
    1550         [ #  # ]:          0 :                 if (flex->map[i].width + pos > data->offset)
    1551                 :            :                         break;
    1552                 :          0 :                 pos += flex->map[i].width;
    1553                 :            :         }
    1554         [ #  # ]:          0 :         if (i >= flex->mapnum)
    1555                 :            :                 return;
    1556         [ #  # ]:          0 :         tmp_ofs = pos < data->offset ? data->offset - pos : 0;
    1557   [ #  #  #  # ]:          0 :         for (j = i; i < flex->mapnum && width_left > 0; ) {
    1558                 :          0 :                 map = flex->map + i;
    1559                 :          0 :                 id = mlx5_flex_get_sample_id(flex, i, &pos, false);
    1560         [ #  # ]:          0 :                 if (id == -1) {
    1561                 :          0 :                         i++;
    1562                 :            :                         /* All left length is dummy */
    1563         [ #  # ]:          0 :                         if (pos >= data->offset + width)
    1564                 :            :                                 return;
    1565                 :          0 :                         cur_width = map->width;
    1566                 :            :                 /* One mapping instance covers the whole width. */
    1567         [ #  # ]:          0 :                 } else if (pos + map->width >= (data->offset + width)) {
    1568                 :            :                         cur_width = width_left;
    1569                 :            :                 } else {
    1570                 :          0 :                         cur_width = cur_width + map->width - tmp_ofs;
    1571                 :          0 :                         pos += map->width;
    1572                 :            :                         /*
    1573                 :            :                          * Continue to search next until:
    1574                 :            :                          * 1. Another flex parser ID.
    1575                 :            :                          * 2. Width has been covered.
    1576                 :            :                          */
    1577         [ #  # ]:          0 :                         for (j = i + 1; j < flex->mapnum; j++) {
    1578                 :          0 :                                 tmp_id = mlx5_flex_get_sample_id(flex, j, &pos, false);
    1579         [ #  # ]:          0 :                                 if (tmp_id == -1) {
    1580                 :            :                                         i = j;
    1581                 :          0 :                                         pos -= flex->map[j].width;
    1582                 :          0 :                                         break;
    1583                 :            :                                 }
    1584   [ #  #  #  # ]:          0 :                                 if (id >= (int)flex->devx_fp->num_samples ||
    1585         [ #  # ]:          0 :                                     id >= MLX5_GRAPH_NODE_SAMPLE_NUM ||
    1586         [ #  # ]:          0 :                                     tmp_id >= (int)flex->devx_fp->num_samples ||
    1587                 :            :                                     tmp_id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
    1588                 :            :                                         return;
    1589                 :          0 :                                 if (flex->devx_fp->sample_info[id].modify_field_id !=
    1590         [ #  # ]:          0 :                                     flex->devx_fp->sample_info[tmp_id].modify_field_id ||
    1591                 :          0 :                                     flex->map[j].shift != flex->map[j - 1].width +
    1592         [ #  # ]:          0 :                                                           flex->map[j - 1].shift) {
    1593                 :            :                                         i = j;
    1594                 :            :                                         break;
    1595                 :            :                                 }
    1596         [ #  # ]:          0 :                                 if ((pos + flex->map[j].width) >= (data->offset + width)) {
    1597                 :            :                                         cur_width = width_left;
    1598                 :            :                                         break;
    1599                 :            :                                 }
    1600                 :          0 :                                 pos += flex->map[j].width;
    1601                 :          0 :                                 cur_width += flex->map[j].width;
    1602                 :            :                         }
    1603                 :            :                 }
    1604         [ #  # ]:          0 :                 if (cur_width > width_left)
    1605                 :            :                         cur_width = width_left;
    1606   [ #  #  #  #  :          0 :                 else if (cur_width < width_left && (j == flex->mapnum || i == flex->mapnum))
                   #  # ]
    1607                 :            :                         return;
    1608                 :            : 
    1609                 :            :                 MLX5_ASSERT(id < (int)flex->devx_fp->num_samples);
    1610   [ #  #  #  # ]:          0 :                 if (id >= (int)flex->devx_fp->num_samples || id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
    1611                 :            :                         return;
    1612                 :            :                 /* Use invalid entry as placeholder for DUMMY mapping. */
    1613                 :          0 :                 info[idx] = (struct field_modify_info){cur_width / CHAR_BIT, offset / CHAR_BIT,
    1614         [ #  # ]:          0 :                              id == -1 ? MLX5_MODI_INVALID :
    1615                 :            :                              (enum mlx5_modification_field)
    1616                 :          0 :                              flex->devx_fp->sample_info[id].modify_field_id,
    1617                 :          0 :                              map->shift + tmp_ofs, 1};
    1618                 :          0 :                 offset += cur_width;
    1619                 :          0 :                 width_left -= cur_width;
    1620         [ #  # ]:          0 :                 if (!mask) {
    1621                 :          0 :                         info[idx].offset = (32 - cur_width - map->shift - tmp_ofs);
    1622                 :          0 :                         info[idx].size = cur_width / CHAR_BIT + info[idx].offset / CHAR_BIT;
    1623                 :            :                 }
    1624                 :            :                 cur_width = 0;
    1625                 :            :                 tmp_ofs = 0;
    1626                 :          0 :                 idx++;
    1627                 :            :         }
    1628         [ #  # ]:          0 :         if (unlikely(width_left > 0)) {
    1629                 :            :                 MLX5_ASSERT(false);
    1630                 :            :                 return;
    1631                 :            :         }
    1632         [ #  # ]:          0 :         if (mask)
    1633                 :          0 :                 memset(mask, 0xff, data->offset / CHAR_BIT + width / CHAR_BIT);
    1634                 :            :         /* Re-order the info to follow IPv6 address. */
    1635         [ #  # ]:          0 :         for (i = 0; i < idx / 2; i++) {
    1636                 :          0 :                 tmp = info[i];
    1637                 :            :                 MLX5_ASSERT(info[i].id);
    1638                 :            :                 MLX5_ASSERT(info[idx - 1 - i].id);
    1639                 :          0 :                 info[i] = info[idx - 1 - i];
    1640                 :          0 :                 info[idx - 1 - i] = tmp;
    1641                 :            :         }
    1642                 :            : }
    1643                 :            : 
    1644                 :            : void
    1645                 :          0 : mlx5_flow_field_id_to_modify_info
    1646                 :            :                 (const struct rte_flow_field_data *data,
    1647                 :            :                  struct field_modify_info *info, uint32_t *mask,
    1648                 :            :                  uint32_t width, struct rte_eth_dev *dev,
    1649                 :            :                  const struct rte_flow_attr *attr, struct rte_flow_error *error)
    1650                 :            : {
    1651                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1652                 :            :         enum mlx5_modification_field modi_id;
    1653                 :            :         uint32_t idx = 0;
    1654                 :            :         uint32_t off_be = 0;
    1655                 :            :         uint32_t length = 0;
    1656                 :            : 
    1657   [ #  #  #  #  :          0 :         switch ((int)data->field) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1658                 :            :         case RTE_FLOW_FIELD_START:
    1659                 :            :                 /* not supported yet */
    1660                 :            :                 MLX5_ASSERT(false);
    1661                 :            :                 break;
    1662                 :          0 :         case RTE_FLOW_FIELD_MAC_DST:
    1663                 :            :                 MLX5_ASSERT(data->offset + width <= 48);
    1664                 :          0 :                 off_be = 48 - (data->offset + width);
    1665         [ #  # ]:          0 :                 if (off_be < 16) {
    1666         [ #  # ]:          0 :                         modi_id = CALC_MODI_ID(DMAC_15_0, data->level);
    1667                 :          0 :                         info[idx] = (struct field_modify_info){2, 4, modi_id};
    1668         [ #  # ]:          0 :                         length = off_be + width <= 16 ? width : 16 - off_be;
    1669         [ #  # ]:          0 :                         if (mask)
    1670                 :          0 :                                 mask[1] = flow_modify_info_mask_16(length,
    1671                 :            :                                                                    off_be);
    1672                 :            :                         else
    1673                 :          0 :                                 info[idx].offset = off_be;
    1674                 :          0 :                         width -= length;
    1675         [ #  # ]:          0 :                         if (!width)
    1676                 :            :                                 break;
    1677                 :            :                         off_be = 0;
    1678                 :            :                         idx++;
    1679                 :            :                 } else {
    1680                 :          0 :                         off_be -= 16;
    1681                 :            :                 }
    1682         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(DMAC_47_16, data->level);
    1683                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1684         [ #  # ]:          0 :                 if (mask)
    1685                 :          0 :                         mask[0] = flow_modify_info_mask_32(width, off_be);
    1686                 :            :                 else
    1687                 :          0 :                         info[idx].offset = off_be;
    1688                 :            :                 break;
    1689                 :          0 :         case RTE_FLOW_FIELD_MAC_SRC:
    1690                 :            :                 MLX5_ASSERT(data->offset + width <= 48);
    1691                 :          0 :                 off_be = 48 - (data->offset + width);
    1692         [ #  # ]:          0 :                 if (off_be < 16) {
    1693         [ #  # ]:          0 :                         modi_id = CALC_MODI_ID(SMAC_15_0, data->level);
    1694                 :          0 :                         info[idx] = (struct field_modify_info){2, 4, modi_id};
    1695         [ #  # ]:          0 :                         length = off_be + width <= 16 ? width : 16 - off_be;
    1696         [ #  # ]:          0 :                         if (mask)
    1697                 :          0 :                                 mask[1] = flow_modify_info_mask_16(length,
    1698                 :            :                                                                    off_be);
    1699                 :            :                         else
    1700                 :          0 :                                 info[idx].offset = off_be;
    1701                 :          0 :                         width -= length;
    1702         [ #  # ]:          0 :                         if (!width)
    1703                 :            :                                 break;
    1704                 :            :                         off_be = 0;
    1705                 :            :                         idx++;
    1706                 :            :                 } else {
    1707                 :          0 :                         off_be -= 16;
    1708                 :            :                 }
    1709         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(SMAC_47_16, data->level);
    1710                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1711         [ #  # ]:          0 :                 if (mask)
    1712                 :          0 :                         mask[0] = flow_modify_info_mask_32(width, off_be);
    1713                 :            :                 else
    1714                 :          0 :                         info[idx].offset = off_be;
    1715                 :            :                 break;
    1716                 :            :         case RTE_FLOW_FIELD_VLAN_TYPE:
    1717                 :            :                 /* not supported yet */
    1718                 :            :                 break;
    1719                 :          0 :         case RTE_FLOW_FIELD_VLAN_ID:
    1720                 :            :                 MLX5_ASSERT(data->offset + width <= 12);
    1721                 :          0 :                 off_be = 12 - (data->offset + width);
    1722                 :          0 :                 info[idx] = (struct field_modify_info){2, 0,
    1723                 :            :                                         MLX5_MODI_OUT_FIRST_VID};
    1724         [ #  # ]:          0 :                 if (mask)
    1725                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1726                 :            :                 else
    1727                 :          0 :                         info[idx].offset = off_be;
    1728                 :            :                 break;
    1729                 :          0 :         case RTE_FLOW_FIELD_MAC_TYPE:
    1730                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1731                 :          0 :                 off_be = 16 - (data->offset + width);
    1732         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(ETHERTYPE, data->level);
    1733                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1734         [ #  # ]:          0 :                 if (mask)
    1735                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1736                 :            :                 else
    1737                 :          0 :                         info[idx].offset = off_be;
    1738                 :            :                 break;
    1739                 :          0 :         case RTE_FLOW_FIELD_IPV4_IHL:
    1740                 :            :                 MLX5_ASSERT(data->offset + width <= 4);
    1741                 :          0 :                 off_be = 4 - (data->offset + width);
    1742         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_IHL, data->level);
    1743                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1744         [ #  # ]:          0 :                 if (mask)
    1745                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1746                 :            :                 else
    1747                 :          0 :                         info[idx].offset = off_be;
    1748                 :            :                 break;
    1749                 :          0 :         case RTE_FLOW_FIELD_IPV4_DSCP:
    1750                 :            :                 MLX5_ASSERT(data->offset + width <= 6);
    1751                 :          0 :                 off_be = 6 - (data->offset + width);
    1752         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IP_DSCP, data->level);
    1753                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1754         [ #  # ]:          0 :                 if (mask)
    1755                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1756                 :            :                 else
    1757                 :          0 :                         info[idx].offset = off_be;
    1758                 :            :                 break;
    1759                 :          0 :         case RTE_FLOW_FIELD_IPV4_TOTAL_LEN:
    1760                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1761                 :          0 :                 off_be = 16 - (data->offset + width);
    1762         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_TOTAL_LEN, data->level);
    1763                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1764         [ #  # ]:          0 :                 if (mask)
    1765                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1766                 :            :                 else
    1767                 :          0 :                         info[idx].offset = off_be;
    1768                 :            :                 break;
    1769                 :          0 :         case RTE_FLOW_FIELD_IPV4_TTL:
    1770                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1771                 :          0 :                 off_be = 8 - (data->offset + width);
    1772         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV4_TTL, data->level);
    1773                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1774         [ #  # ]:          0 :                 if (mask)
    1775                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1776                 :            :                 else
    1777                 :          0 :                         info[idx].offset = off_be;
    1778                 :            :                 break;
    1779                 :          0 :         case RTE_FLOW_FIELD_IPV4_SRC:
    1780                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1781                 :          0 :                 off_be = 32 - (data->offset + width);
    1782         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(SIPV4, data->level);
    1783                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1784         [ #  # ]:          0 :                 if (mask)
    1785                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1786                 :            :                 else
    1787                 :          0 :                         info[idx].offset = off_be;
    1788                 :            :                 break;
    1789                 :          0 :         case RTE_FLOW_FIELD_IPV4_DST:
    1790                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1791                 :          0 :                 off_be = 32 - (data->offset + width);
    1792         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(DIPV4, data->level);
    1793                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1794         [ #  # ]:          0 :                 if (mask)
    1795                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1796                 :            :                 else
    1797                 :          0 :                         info[idx].offset = off_be;
    1798                 :            :                 break;
    1799                 :            :         case RTE_FLOW_FIELD_IPV6_DSCP:
    1800                 :            :                 MLX5_ASSERT(data->offset + width <= 6);
    1801                 :            :                 /*
    1802                 :            :                  * IPv6 DSCP uses OUT_IPV6_TRAFFIC_CLASS as ID but it starts from 2
    1803                 :            :                  * bits left. Shift the mask left for IPv6 DSCP. Do it here because
    1804                 :            :                  * it's needed to distinguish DSCP from ECN in data field construct
    1805                 :            :                  */
    1806         [ #  # ]:          0 :                 if (mlx5_dv_modify_ipv6_traffic_class_supported(priv)) {
    1807                 :          0 :                         off_be = 6 - (data->offset + width) + MLX5_IPV6_HDR_DSCP_SHIFT;
    1808                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    1809                 :            :                                                 MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS};
    1810                 :            :                 } else {
    1811                 :          0 :                         off_be = 6 - (data->offset + width);
    1812                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    1813                 :            :                                                 MLX5_MODI_OUT_IP_DSCP};
    1814                 :            :                 }
    1815         [ #  # ]:          0 :                 if (mask)
    1816                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1817                 :            :                 else
    1818                 :          0 :                         info[idx].offset = off_be;
    1819                 :            :                 break;
    1820                 :          0 :         case RTE_FLOW_FIELD_IPV6_TRAFFIC_CLASS:
    1821                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1822                 :          0 :                 off_be = 8 - (data->offset + width);
    1823         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_TRAFFIC_CLASS, data->level);
    1824                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1825         [ #  # ]:          0 :                 if (mask)
    1826                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1827                 :            :                 else
    1828                 :          0 :                         info[idx].offset = off_be;
    1829                 :            :                 break;
    1830                 :          0 :         case RTE_FLOW_FIELD_IPV6_FLOW_LABEL:
    1831                 :            :                 MLX5_ASSERT(data->offset + width <= 20);
    1832                 :          0 :                 off_be = 20 - (data->offset + width);
    1833         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_FLOW_LABEL, data->level);
    1834                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1835         [ #  # ]:          0 :                 if (mask)
    1836                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1837                 :            :                 else
    1838                 :          0 :                         info[idx].offset = off_be;
    1839                 :            :                 break;
    1840                 :          0 :         case RTE_FLOW_FIELD_IPV6_PAYLOAD_LEN:
    1841                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1842                 :          0 :                 off_be = 16 - (data->offset + width);
    1843         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_PAYLOAD_LEN, data->level);
    1844                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1845         [ #  # ]:          0 :                 if (mask)
    1846                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1847                 :            :                 else
    1848                 :          0 :                         info[idx].offset = off_be;
    1849                 :            :                 break;
    1850                 :          0 :         case RTE_FLOW_FIELD_IPV6_HOPLIMIT:
    1851                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    1852                 :          0 :                 off_be = 8 - (data->offset + width);
    1853         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IPV6_HOPLIMIT, data->level);
    1854                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    1855         [ #  # ]:          0 :                 if (mask)
    1856                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    1857                 :            :                 else
    1858                 :          0 :                         info[idx].offset = off_be;
    1859                 :            :                 break;
    1860                 :          0 :         case RTE_FLOW_FIELD_IPV6_SRC: {
    1861                 :            :                 /*
    1862                 :            :                  * Fields corresponding to IPv6 source address bytes
    1863                 :            :                  * arranged according to network byte ordering.
    1864                 :            :                  */
    1865                 :          0 :                 struct field_modify_info fields[] = {
    1866         [ #  # ]:          0 :                         { 4, 0, CALC_MODI_ID(SIPV6_127_96, data->level)},
    1867         [ #  # ]:          0 :                         { 4, 4, CALC_MODI_ID(SIPV6_95_64, data->level)},
    1868         [ #  # ]:          0 :                         { 4, 8, CALC_MODI_ID(SIPV6_63_32, data->level)},
    1869         [ #  # ]:          0 :                         { 4, 12, CALC_MODI_ID(SIPV6_31_0, data->level)},
    1870                 :            :                 };
    1871                 :            :                 /* First mask to be modified is the mask of 4th address byte. */
    1872                 :            :                 uint32_t midx = 3;
    1873                 :            : 
    1874                 :            :                 MLX5_ASSERT(data->offset + width <= 128);
    1875                 :          0 :                 off_be = 128 - (data->offset + width);
    1876         [ #  # ]:          0 :                 while (width > 0 && midx > 0) {
    1877         [ #  # ]:          0 :                         if (off_be < 32) {
    1878                 :          0 :                                 info[idx] = fields[midx];
    1879                 :          0 :                                 length = off_be + width <= 32 ?
    1880         [ #  # ]:          0 :                                          width : 32 - off_be;
    1881         [ #  # ]:          0 :                                 if (mask)
    1882         [ #  # ]:          0 :                                         mask[midx] = flow_modify_info_mask_32
    1883                 :            :                                                 (length, off_be);
    1884                 :            :                                 else
    1885                 :          0 :                                         info[idx].offset = off_be;
    1886                 :          0 :                                 width -= length;
    1887                 :            :                                 off_be = 0;
    1888                 :          0 :                                 idx++;
    1889                 :            :                         } else {
    1890                 :          0 :                                 off_be -= 32;
    1891                 :            :                         }
    1892                 :          0 :                         midx--;
    1893                 :            :                 }
    1894         [ #  # ]:          0 :                 if (!width)
    1895                 :            :                         break;
    1896                 :          0 :                 info[idx] = fields[midx];
    1897         [ #  # ]:          0 :                 if (mask)
    1898         [ #  # ]:          0 :                         mask[midx] = flow_modify_info_mask_32(width, off_be);
    1899                 :            :                 else
    1900                 :          0 :                         info[idx].offset = off_be;
    1901                 :            :                 break;
    1902                 :            :         }
    1903                 :          0 :         case RTE_FLOW_FIELD_IPV6_DST: {
    1904                 :            :                 /*
    1905                 :            :                  * Fields corresponding to IPv6 destination address bytes
    1906                 :            :                  * arranged according to network byte ordering.
    1907                 :            :                  */
    1908                 :          0 :                 struct field_modify_info fields[] = {
    1909         [ #  # ]:          0 :                         { 4, 0, CALC_MODI_ID(DIPV6_127_96, data->level)},
    1910         [ #  # ]:          0 :                         { 4, 4, CALC_MODI_ID(DIPV6_95_64, data->level)},
    1911         [ #  # ]:          0 :                         { 4, 8, CALC_MODI_ID(DIPV6_63_32, data->level)},
    1912         [ #  # ]:          0 :                         { 4, 12, CALC_MODI_ID(DIPV6_31_0, data->level)},
    1913                 :            :                 };
    1914                 :            :                 /* First mask to be modified is the mask of 4th address byte. */
    1915                 :            :                 uint32_t midx = 3;
    1916                 :            : 
    1917                 :            :                 MLX5_ASSERT(data->offset + width <= 128);
    1918                 :          0 :                 off_be = 128 - (data->offset + width);
    1919         [ #  # ]:          0 :                 while (width > 0 && midx > 0) {
    1920         [ #  # ]:          0 :                         if (off_be < 32) {
    1921                 :          0 :                                 info[idx] = fields[midx];
    1922                 :          0 :                                 length = off_be + width <= 32 ?
    1923         [ #  # ]:          0 :                                          width : 32 - off_be;
    1924         [ #  # ]:          0 :                                 if (mask)
    1925         [ #  # ]:          0 :                                         mask[midx] = flow_modify_info_mask_32
    1926                 :            :                                                 (length, off_be);
    1927                 :            :                                 else
    1928                 :          0 :                                         info[idx].offset = off_be;
    1929                 :          0 :                                 width -= length;
    1930                 :            :                                 off_be = 0;
    1931                 :          0 :                                 idx++;
    1932                 :            :                         } else {
    1933                 :          0 :                                 off_be -= 32;
    1934                 :            :                         }
    1935                 :          0 :                         midx--;
    1936                 :            :                 }
    1937         [ #  # ]:          0 :                 if (!width)
    1938                 :            :                         break;
    1939                 :          0 :                 info[idx] = fields[midx];
    1940         [ #  # ]:          0 :                 if (mask)
    1941         [ #  # ]:          0 :                         mask[midx] = flow_modify_info_mask_32(width, off_be);
    1942                 :            :                 else
    1943                 :          0 :                         info[idx].offset = off_be;
    1944                 :            :                 break;
    1945                 :            :         }
    1946                 :          0 :         case RTE_FLOW_FIELD_TCP_PORT_SRC:
    1947                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1948                 :          0 :                 off_be = 16 - (data->offset + width);
    1949         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_SPORT, data->level);
    1950                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1951         [ #  # ]:          0 :                 if (mask)
    1952                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1953                 :            :                 else
    1954                 :          0 :                         info[idx].offset = off_be;
    1955                 :            :                 break;
    1956                 :          0 :         case RTE_FLOW_FIELD_TCP_PORT_DST:
    1957                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    1958                 :          0 :                 off_be = 16 - (data->offset + width);
    1959         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_DPORT, data->level);
    1960                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1961         [ #  # ]:          0 :                 if (mask)
    1962                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1963                 :            :                 else
    1964                 :          0 :                         info[idx].offset = off_be;
    1965                 :            :                 break;
    1966                 :          0 :         case RTE_FLOW_FIELD_TCP_SEQ_NUM:
    1967                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1968                 :          0 :                 off_be = 32 - (data->offset + width);
    1969         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_SEQ_NUM, data->level);
    1970                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1971         [ #  # ]:          0 :                 if (mask)
    1972                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1973                 :            :                 else
    1974                 :          0 :                         info[idx].offset = off_be;
    1975                 :            :                 break;
    1976                 :          0 :         case RTE_FLOW_FIELD_TCP_ACK_NUM:
    1977                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    1978                 :          0 :                 off_be = 32 - (data->offset + width);
    1979         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_ACK_NUM, data->level);
    1980                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    1981         [ #  # ]:          0 :                 if (mask)
    1982                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    1983                 :            :                 else
    1984                 :          0 :                         info[idx].offset = off_be;
    1985                 :            :                 break;
    1986                 :          0 :         case RTE_FLOW_FIELD_TCP_FLAGS:
    1987                 :            :                 MLX5_ASSERT(data->offset + width <= 9);
    1988                 :          0 :                 off_be = 9 - (data->offset + width);
    1989         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_FLAGS, data->level);
    1990                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    1991         [ #  # ]:          0 :                 if (mask)
    1992                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    1993                 :            :                 else
    1994                 :          0 :                         info[idx].offset = off_be;
    1995                 :            :                 break;
    1996                 :          0 :         case RTE_FLOW_FIELD_TCP_DATA_OFFSET:
    1997                 :            :                 MLX5_ASSERT(data->offset + width <= 4);
    1998                 :          0 :                 off_be = 4 - (data->offset + width);
    1999         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(TCP_DATA_OFFSET, data->level);
    2000                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    2001         [ #  # ]:          0 :                 if (mask)
    2002                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2003                 :            :                 else
    2004                 :          0 :                         info[idx].offset = off_be;
    2005                 :            :                 break;
    2006                 :          0 :         case RTE_FLOW_FIELD_UDP_PORT_SRC:
    2007                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2008                 :          0 :                 off_be = 16 - (data->offset + width);
    2009         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(UDP_SPORT, data->level);
    2010                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    2011         [ #  # ]:          0 :                 if (mask)
    2012                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    2013                 :            :                 else
    2014                 :          0 :                         info[idx].offset = off_be;
    2015                 :            :                 break;
    2016                 :          0 :         case RTE_FLOW_FIELD_UDP_PORT_DST:
    2017                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2018                 :          0 :                 off_be = 16 - (data->offset + width);
    2019         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(UDP_DPORT, data->level);
    2020                 :          0 :                 info[idx] = (struct field_modify_info){2, 0, modi_id};
    2021         [ #  # ]:          0 :                 if (mask)
    2022                 :          0 :                         mask[idx] = flow_modify_info_mask_16(width, off_be);
    2023                 :            :                 else
    2024                 :          0 :                         info[idx].offset = off_be;
    2025                 :            :                 break;
    2026                 :          0 :         case RTE_FLOW_FIELD_VXLAN_VNI:
    2027                 :            :         case RTE_FLOW_FIELD_GENEVE_VNI:
    2028                 :            :                 MLX5_ASSERT(data->offset + width <= 24);
    2029                 :            :                 /* VNI is on bits 31-8 of TUNNEL_HDR_DW_1. */
    2030                 :          0 :                 off_be = 24 - (data->offset + width) + 8;
    2031                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2032                 :            :                                         MLX5_MODI_TUNNEL_HDR_DW_1};
    2033         [ #  # ]:          0 :                 if (mask)
    2034                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2035                 :            :                 else
    2036                 :          0 :                         info[idx].offset = off_be;
    2037                 :            :                 break;
    2038                 :          0 :         case RTE_FLOW_FIELD_VXLAN_LAST_RSVD:
    2039                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2040                 :            :                 /* Last_rsvd is on bits 7-0 of TUNNEL_HDR_DW_1. */
    2041                 :          0 :                 off_be = 8 - (data->offset + width);
    2042                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, MLX5_MODI_TUNNEL_HDR_DW_1};
    2043         [ #  # ]:          0 :                 if (mask)
    2044                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2045                 :            :                 else
    2046                 :          0 :                         info[idx].offset = off_be;
    2047                 :            :                 break;
    2048                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_TYPE:
    2049                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2050                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2051         [ #  # ]:          0 :                 if (modi_id < 0)
    2052                 :            :                         return;
    2053                 :            :                 /* Type is on bits 16-8 of GENEVE option header (DW0). */
    2054                 :          0 :                 off_be = 32 - (16 + data->offset + width);
    2055                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2056         [ #  # ]:          0 :                 if (mask)
    2057                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2058                 :            :                 else
    2059                 :          0 :                         info[idx].offset = off_be;
    2060                 :            :                 break;
    2061                 :            :         case RTE_FLOW_FIELD_GENEVE_OPT_CLASS:
    2062                 :            :                 MLX5_ASSERT(data->offset + width <= 16);
    2063                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2064         [ #  # ]:          0 :                 if (modi_id < 0)
    2065                 :            :                         return;
    2066                 :            :                 /* Class is on bits 31-16 of GENEVE option header (DW0). */
    2067                 :          0 :                 off_be = 32 - (data->offset + width);
    2068                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2069         [ #  # ]:          0 :                 if (mask)
    2070                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2071                 :            :                 else
    2072                 :          0 :                         info[idx].offset = off_be;
    2073                 :            :                 break;
    2074                 :          0 :         case RTE_FLOW_FIELD_GENEVE_OPT_DATA:
    2075         [ #  # ]:          0 :                 if ((data->offset % 32) + width > 32) {
    2076                 :          0 :                         DRV_LOG(ERR, "Geneve TLV option data is per DW.");
    2077                 :          0 :                         return;
    2078                 :            :                 }
    2079                 :            :                 modi_id = flow_geneve_opt_modi_field_get(priv, data);
    2080         [ #  # ]:          0 :                 if (modi_id < 0)
    2081                 :            :                         return;
    2082                 :            :                 /* Use offset inside DW. */
    2083                 :          0 :                 off_be = 32 - ((data->offset % 32) + width);
    2084                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2085         [ #  # ]:          0 :                 if (mask)
    2086                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2087                 :            :                 else
    2088                 :          0 :                         info[idx].offset = off_be;
    2089                 :            :                 break;
    2090                 :          0 :         case RTE_FLOW_FIELD_GTP_TEID:
    2091                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2092                 :          0 :                 off_be = 32 - (data->offset + width);
    2093                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2094                 :            :                                         MLX5_MODI_GTP_TEID};
    2095         [ #  # ]:          0 :                 if (mask)
    2096                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2097                 :            :                 else
    2098                 :          0 :                         info[idx].offset = off_be;
    2099                 :            :                 break;
    2100                 :          0 :         case RTE_FLOW_FIELD_MPLS:
    2101                 :            :                 MLX5_ASSERT(data->offset + width <= 32);
    2102                 :          0 :                 off_be = 32 - (data->offset + width);
    2103                 :            :                 modi_id = mlx5_mpls_modi_field_get(data);
    2104                 :          0 :                 info[idx] = (struct field_modify_info){4, 0, modi_id};
    2105         [ #  # ]:          0 :                 if (mask)
    2106                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2107                 :            :                 else
    2108                 :          0 :                         info[idx].offset = off_be;
    2109                 :            :                 break;
    2110                 :            :         case RTE_FLOW_FIELD_TAG:
    2111                 :            :                 {
    2112                 :            :                         MLX5_ASSERT(data->offset + width <= 32);
    2113                 :            :                         uint8_t tag_index = flow_tag_index_get(data);
    2114                 :            :                         int reg;
    2115                 :            : 
    2116                 :            :                         off_be = (tag_index == RTE_PMD_MLX5_LINEAR_HASH_TAG_INDEX) ?
    2117         [ #  # ]:          0 :                                 16 - (data->offset + width) + 16 : data->offset;
    2118         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    2119         [ #  # ]:          0 :                                 reg = flow_hw_get_reg_id(dev,
    2120                 :            :                                                         RTE_FLOW_ITEM_TYPE_TAG,
    2121                 :            :                                                         tag_index);
    2122                 :            :                         else
    2123                 :          0 :                                 reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG,
    2124                 :            :                                                         tag_index, error);
    2125         [ #  # ]:          0 :                         if (reg < 0)
    2126                 :            :                                 return;
    2127                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2128         [ #  # ]:          0 :                         if ((unsigned int)reg >= RTE_DIM(mlx5_reg_to_field))
    2129                 :            :                                 return;
    2130                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2131                 :          0 :                                                 mlx5_reg_to_field[reg]};
    2132         [ #  # ]:          0 :                         if (mask)
    2133                 :          0 :                                 mask[idx] = flow_modify_info_mask_32(width, off_be);
    2134                 :            :                         else
    2135                 :          0 :                                 info[idx].offset = off_be;
    2136                 :            :                 }
    2137                 :            :                 break;
    2138                 :          0 :         case RTE_FLOW_FIELD_MARK:
    2139                 :            :                 {
    2140                 :          0 :                         uint32_t mark_mask = priv->sh->dv_mark_mask;
    2141                 :            :                         uint32_t mark_count = rte_popcount32(mark_mask);
    2142                 :            :                         RTE_SET_USED(mark_count);
    2143                 :            :                         MLX5_ASSERT(data->offset + width <= mark_count);
    2144                 :          0 :                         int reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK,
    2145                 :            :                                                        0, error);
    2146         [ #  # ]:          0 :                         if (reg < 0)
    2147                 :            :                                 return;
    2148                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2149                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(mlx5_reg_to_field));
    2150                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2151                 :          0 :                                                 mlx5_reg_to_field[reg]};
    2152         [ #  # ]:          0 :                         if (mask)
    2153                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2154         [ #  # ]:          0 :                                         (width, data->offset, mark_mask);
    2155                 :            :                         else
    2156                 :          0 :                                 info[idx].offset = data->offset;
    2157                 :            :                 }
    2158                 :            :                 break;
    2159                 :          0 :         case RTE_FLOW_FIELD_META:
    2160                 :            :                 {
    2161                 :          0 :                         uint32_t meta_mask = priv->sh->dv_meta_mask;
    2162                 :            :                         uint32_t meta_count = rte_popcount32(meta_mask);
    2163                 :            :                         RTE_SET_USED(meta_count);
    2164                 :            :                         MLX5_ASSERT(data->offset + width <= meta_count);
    2165                 :          0 :                         int reg = flow_dv_get_metadata_reg(dev, attr, error);
    2166         [ #  # ]:          0 :                         if (reg < 0)
    2167                 :            :                                 return;
    2168                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2169                 :            :                         MLX5_ASSERT((unsigned int)reg < RTE_DIM(mlx5_reg_to_field));
    2170                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2171                 :          0 :                                                 mlx5_reg_to_field[reg]};
    2172         [ #  # ]:          0 :                         if (mask)
    2173                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2174         [ #  # ]:          0 :                                         (width, data->offset, meta_mask);
    2175                 :            :                         else
    2176                 :          0 :                                 info[idx].offset = data->offset;
    2177                 :            :                 }
    2178                 :            :                 break;
    2179                 :          0 :         case RTE_FLOW_FIELD_IPV4_ECN:
    2180                 :            :                 MLX5_ASSERT(data->offset + width <= 2);
    2181                 :          0 :                 off_be = 2 - (data->offset + width);
    2182         [ #  # ]:          0 :                 modi_id = CALC_MODI_ID(IP_ECN, data->level);
    2183                 :          0 :                 info[idx] = (struct field_modify_info){1, 0, modi_id};
    2184         [ #  # ]:          0 :                 if (mask)
    2185                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2186                 :            :                 else
    2187                 :          0 :                         info[idx].offset = off_be;
    2188                 :            :                 break;
    2189                 :          0 :         case RTE_FLOW_FIELD_IPV6_ECN:
    2190                 :            :                 MLX5_ASSERT(data->offset + width <= 2);
    2191         [ #  # ]:          0 :                 off_be = 2 - (data->offset + width);
    2192         [ #  # ]:          0 :                 if (mlx5_dv_modify_ipv6_traffic_class_supported(priv))
    2193                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    2194                 :            :                                                 MLX5_MODI_OUT_IPV6_TRAFFIC_CLASS};
    2195                 :            :                 else
    2196                 :          0 :                         info[idx] = (struct field_modify_info){1, 0,
    2197                 :            :                                                 MLX5_MODI_OUT_IP_ECN};
    2198         [ #  # ]:          0 :                 if (mask)
    2199                 :          0 :                         mask[idx] = flow_modify_info_mask_8(width, off_be);
    2200                 :            :                 else
    2201                 :          0 :                         info[idx].offset = off_be;
    2202                 :            :                 break;
    2203                 :          0 :         case RTE_FLOW_FIELD_GTP_PSC_QFI:
    2204                 :            :                 MLX5_ASSERT(data->offset + width <= 8);
    2205                 :          0 :                 off_be = data->offset + 8;
    2206                 :          0 :                 info[idx] = (struct field_modify_info){4, 0,
    2207                 :            :                                         MLX5_MODI_GTPU_FIRST_EXT_DW_0};
    2208         [ #  # ]:          0 :                 if (mask)
    2209                 :          0 :                         mask[idx] = flow_modify_info_mask_32(width, off_be);
    2210                 :            :                 else
    2211                 :          0 :                         info[idx].offset = off_be;
    2212                 :            :                 break;
    2213                 :          0 :         case MLX5_RTE_FLOW_FIELD_META_REG:
    2214                 :            :                 {
    2215         [ #  # ]:          0 :                         uint32_t meta_mask = priv->sh->dv_meta_mask;
    2216                 :            :                         uint32_t meta_count = rte_popcount32(meta_mask);
    2217                 :            :                         uint8_t reg = flow_tag_index_get(data);
    2218                 :            : 
    2219                 :            :                         RTE_SET_USED(meta_count);
    2220                 :            :                         MLX5_ASSERT(data->offset + width <= meta_count);
    2221                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2222                 :            :                         MLX5_ASSERT(reg < RTE_DIM(mlx5_reg_to_field));
    2223                 :          0 :                         info[idx] = (struct field_modify_info){4, 0, mlx5_reg_to_field[reg]};
    2224         [ #  # ]:          0 :                         if (mask)
    2225                 :          0 :                                 mask[idx] = flow_modify_info_mask_32_masked
    2226         [ #  # ]:          0 :                                         (width, data->offset, meta_mask);
    2227                 :            :                         else
    2228                 :          0 :                                 info[idx].offset = data->offset;
    2229                 :            :                 }
    2230                 :            :                 break;
    2231                 :          0 :         case RTE_FLOW_FIELD_METER_COLOR:
    2232                 :            :                 {
    2233                 :            :                         const uint32_t color_mask =
    2234                 :            :                                 (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
    2235                 :            :                         int reg;
    2236                 :            : 
    2237         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    2238                 :            :                                 reg = flow_hw_get_reg_id
    2239                 :            :                                         (dev,
    2240                 :            :                                         RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
    2241                 :            :                         else
    2242                 :          0 :                                 reg = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
    2243                 :            :                                                 0, error);
    2244         [ #  # ]:          0 :                         if (reg < 0)
    2245                 :            :                                 return;
    2246                 :            :                         MLX5_ASSERT(reg != REG_NON);
    2247         [ #  # ]:          0 :                         if ((unsigned int)reg >= RTE_DIM(mlx5_reg_to_field))
    2248                 :            :                                 return;
    2249                 :          0 :                         info[idx] = (struct field_modify_info){4, 0,
    2250                 :          0 :                                                 mlx5_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 mlx5_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         [ #  # ]:          0 :                 if (spec->flags & ~MLX5_FLOW_CONNTRACK_PKT_STATE_ALL)
    3291                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3292                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM,
    3293                 :            :                                         NULL,
    3294                 :            :                                         "Invalid CT item flags");
    3295                 :            :         }
    3296                 :            :         /* State change also needs to be considered. */
    3297                 :          0 :         *item_flags |= MLX5_FLOW_LAYER_ASO_CT;
    3298                 :          0 :         return 0;
    3299                 :            : }
    3300                 :            : 
    3301                 :            : /**
    3302                 :            :  * Validate the pop VLAN action.
    3303                 :            :  *
    3304                 :            :  * @param[in] dev
    3305                 :            :  *   Pointer to the rte_eth_dev structure.
    3306                 :            :  * @param[in] action_flags
    3307                 :            :  *   Holds the actions detected until now.
    3308                 :            :  * @param[in] action
    3309                 :            :  *   Pointer to the pop vlan action.
    3310                 :            :  * @param[in] item_flags
    3311                 :            :  *   The items found in this flow rule.
    3312                 :            :  * @param[in] attr
    3313                 :            :  *   Pointer to flow attributes.
    3314                 :            :  * @param[out] error
    3315                 :            :  *   Pointer to error structure.
    3316                 :            :  *
    3317                 :            :  * @return
    3318                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3319                 :            :  */
    3320                 :            : static int
    3321                 :          0 : flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
    3322                 :            :                                  uint64_t action_flags,
    3323                 :            :                                  const struct rte_flow_action *action,
    3324                 :            :                                  uint64_t item_flags,
    3325                 :            :                                  const struct rte_flow_attr *attr,
    3326                 :            :                                  struct rte_flow_error *error)
    3327                 :            : {
    3328                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3329                 :            : 
    3330         [ #  # ]:          0 :         if (!priv->sh->pop_vlan_action)
    3331                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3332                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3333                 :            :                                           NULL,
    3334                 :            :                                           "pop vlan action is not supported");
    3335         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_VLAN_ACTIONS)
    3336                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3337                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3338                 :            :                                           "no support for multiple VLAN "
    3339                 :            :                                           "actions");
    3340                 :            :         /* Pop VLAN with preceding Decap requires inner header with VLAN. */
    3341         [ #  # ]:          0 :         if ((action_flags & MLX5_FLOW_ACTION_DECAP) &&
    3342         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_INNER_VLAN))
    3343                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3344                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3345                 :            :                                           NULL,
    3346                 :            :                                           "cannot pop vlan after decap without "
    3347                 :            :                                           "match on inner vlan in the flow");
    3348                 :            :         /* Pop VLAN without preceding Decap requires outer header with VLAN. */
    3349         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_DECAP) &&
    3350         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
    3351                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3352                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3353                 :            :                                           NULL,
    3354                 :            :                                           "cannot pop vlan without a "
    3355                 :            :                                           "match on (outer) vlan in the flow");
    3356         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3357                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3358                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3359                 :            :                                           "wrong action order, port_id should "
    3360                 :            :                                           "be after pop VLAN action");
    3361   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3362                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3363                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3364                 :            :                                           "pop vlan action for VF representor "
    3365                 :            :                                           "not supported on NIC table");
    3366                 :            :         return 0;
    3367                 :            : }
    3368                 :            : 
    3369                 :            : /**
    3370                 :            :  * Get VLAN default info from vlan match info.
    3371                 :            :  *
    3372                 :            :  * @param[in] items
    3373                 :            :  *   the list of item specifications.
    3374                 :            :  * @param[out] vlan
    3375                 :            :  *   pointer VLAN info to fill to.
    3376                 :            :  *
    3377                 :            :  * @return
    3378                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3379                 :            :  */
    3380                 :            : static void
    3381                 :          0 : flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items,
    3382                 :            :                                   struct rte_vlan_hdr *vlan)
    3383                 :            : {
    3384                 :          0 :         const struct rte_flow_item_vlan nic_mask = {
    3385                 :            :                 .hdr.vlan_tci = RTE_BE16(MLX5DV_FLOW_VLAN_PCP_MASK |
    3386                 :            :                                 MLX5DV_FLOW_VLAN_VID_MASK),
    3387                 :            :                 .hdr.eth_proto = RTE_BE16(0xffff),
    3388                 :            :         };
    3389                 :            : 
    3390         [ #  # ]:          0 :         if (items == NULL)
    3391                 :          0 :                 return;
    3392         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    3393                 :          0 :                 int type = items->type;
    3394                 :            : 
    3395                 :          0 :                 if (type == RTE_FLOW_ITEM_TYPE_VLAN ||
    3396         [ #  # ]:          0 :                     type == MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
    3397                 :            :                         break;
    3398                 :            :         }
    3399         [ #  # ]:          0 :         if (items->type != RTE_FLOW_ITEM_TYPE_END) {
    3400                 :          0 :                 const struct rte_flow_item_vlan *vlan_m = items->mask;
    3401                 :          0 :                 const struct rte_flow_item_vlan *vlan_v = items->spec;
    3402                 :            : 
    3403                 :            :                 /* If VLAN item in pattern doesn't contain data, return here. */
    3404         [ #  # ]:          0 :                 if (!vlan_v)
    3405                 :            :                         return;
    3406         [ #  # ]:          0 :                 if (!vlan_m)
    3407                 :            :                         vlan_m = &nic_mask;
    3408                 :            :                 /* Only full match values are accepted */
    3409         [ #  # ]:          0 :                 if ((vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) ==
    3410                 :            :                      MLX5DV_FLOW_VLAN_PCP_MASK_BE) {
    3411                 :          0 :                         vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK;
    3412                 :          0 :                         vlan->vlan_tci |=
    3413         [ #  # ]:          0 :                                 rte_be_to_cpu_16(vlan_v->hdr.vlan_tci &
    3414                 :            :                                                  MLX5DV_FLOW_VLAN_PCP_MASK_BE);
    3415                 :            :                 }
    3416         [ #  # ]:          0 :                 if ((vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) ==
    3417                 :            :                      MLX5DV_FLOW_VLAN_VID_MASK_BE) {
    3418                 :          0 :                         vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_VID_MASK;
    3419                 :          0 :                         vlan->vlan_tci |=
    3420         [ #  # ]:          0 :                                 rte_be_to_cpu_16(vlan_v->hdr.vlan_tci &
    3421                 :            :                                                  MLX5DV_FLOW_VLAN_VID_MASK_BE);
    3422                 :            :                 }
    3423         [ #  # ]:          0 :                 if (vlan_m->hdr.eth_proto == nic_mask.hdr.eth_proto)
    3424         [ #  # ]:          0 :                         vlan->eth_proto = rte_be_to_cpu_16(vlan_v->hdr.eth_proto &
    3425                 :            :                                                            vlan_m->hdr.eth_proto);
    3426                 :            :         }
    3427                 :            : }
    3428                 :            : 
    3429                 :            : /**
    3430                 :            :  * Validate the push VLAN action.
    3431                 :            :  *
    3432                 :            :  * @param[in] dev
    3433                 :            :  *   Pointer to the rte_eth_dev structure.
    3434                 :            :  * @param[in] action_flags
    3435                 :            :  *   Holds the actions detected until now.
    3436                 :            :  * @param[in] item_flags
    3437                 :            :  *   The items found in this flow rule.
    3438                 :            :  * @param[in] action
    3439                 :            :  *   Pointer to the action structure.
    3440                 :            :  * @param[in] attr
    3441                 :            :  *   Pointer to flow attributes
    3442                 :            :  * @param[out] error
    3443                 :            :  *   Pointer to error structure.
    3444                 :            :  *
    3445                 :            :  * @return
    3446                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3447                 :            :  */
    3448                 :            : static int
    3449                 :          0 : flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev,
    3450                 :            :                                   uint64_t action_flags,
    3451                 :            :                                   const struct rte_flow_item_vlan *vlan_m,
    3452                 :            :                                   const struct rte_flow_action *action,
    3453                 :            :                                   const struct rte_flow_attr *attr,
    3454                 :            :                                   struct rte_flow_error *error)
    3455                 :            : {
    3456                 :          0 :         const struct rte_flow_action_of_push_vlan *push_vlan = action->conf;
    3457                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3458                 :            : 
    3459         [ #  # ]:          0 :         if (push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_VLAN) &&
    3460                 :            :             push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_QINQ))
    3461                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3462                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3463                 :            :                                           "invalid vlan ethertype");
    3464         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3465                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3466                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3467                 :            :                                           "wrong action order, port_id should "
    3468                 :            :                                           "be after push VLAN");
    3469   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3470                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3471                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3472                 :            :                                           "push vlan action for VF representor "
    3473                 :            :                                           "not supported on NIC table");
    3474         [ #  # ]:          0 :         if (vlan_m &&
    3475   [ #  #  #  # ]:          0 :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) &&
    3476                 :            :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) !=
    3477                 :          0 :                 MLX5DV_FLOW_VLAN_PCP_MASK_BE &&
    3478   [ #  #  #  # ]:          0 :             !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP) &&
    3479                 :          0 :             !(mlx5_flow_find_action
    3480                 :            :                 (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP)))
    3481                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3482                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3483                 :            :                                           "not full match mask on VLAN PCP and "
    3484                 :            :                                           "there is no of_set_vlan_pcp action, "
    3485                 :            :                                           "push VLAN action cannot figure out "
    3486                 :            :                                           "PCP value");
    3487         [ #  # ]:          0 :         if (vlan_m &&
    3488   [ #  #  #  # ]:          0 :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) &&
    3489                 :            :             (vlan_m->hdr.vlan_tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) !=
    3490                 :          0 :                 MLX5DV_FLOW_VLAN_VID_MASK_BE &&
    3491   [ #  #  #  # ]:          0 :             !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID) &&
    3492                 :          0 :             !(mlx5_flow_find_action
    3493                 :            :                 (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)))
    3494                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3495                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3496                 :            :                                           "not full match mask on VLAN VID and "
    3497                 :            :                                           "there is no of_set_vlan_vid action, "
    3498                 :            :                                           "push VLAN action cannot figure out "
    3499                 :            :                                           "VID value");
    3500                 :            :         (void)attr;
    3501                 :            :         return 0;
    3502                 :            : }
    3503                 :            : 
    3504                 :            : /**
    3505                 :            :  * Validate the set VLAN PCP.
    3506                 :            :  *
    3507                 :            :  * @param[in] action_flags
    3508                 :            :  *   Holds the actions detected until now.
    3509                 :            :  * @param[in] actions
    3510                 :            :  *   Pointer to the list of actions remaining in the flow rule.
    3511                 :            :  * @param[out] error
    3512                 :            :  *   Pointer to error structure.
    3513                 :            :  *
    3514                 :            :  * @return
    3515                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3516                 :            :  */
    3517                 :            : static int
    3518                 :          0 : flow_dv_validate_action_set_vlan_pcp(uint64_t action_flags,
    3519                 :            :                                      const struct rte_flow_action actions[],
    3520                 :            :                                      struct rte_flow_error *error)
    3521                 :            : {
    3522                 :            :         const struct rte_flow_action *action = actions;
    3523                 :          0 :         const struct rte_flow_action_of_set_vlan_pcp *conf = action->conf;
    3524                 :            : 
    3525         [ #  # ]:          0 :         if (conf->vlan_pcp > 7)
    3526                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3527                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3528                 :            :                                           "VLAN PCP value is too big");
    3529         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN))
    3530                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3531                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3532                 :            :                                           "set VLAN PCP action must follow "
    3533                 :            :                                           "the push VLAN action");
    3534         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP)
    3535                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3536                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3537                 :            :                                           "Multiple VLAN PCP modification are "
    3538                 :            :                                           "not supported");
    3539         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3540                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3541                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3542                 :            :                                           "wrong action order, port_id should "
    3543                 :            :                                           "be after set VLAN PCP");
    3544                 :            :         return 0;
    3545                 :            : }
    3546                 :            : 
    3547                 :            : /**
    3548                 :            :  * Validate the set VLAN VID.
    3549                 :            :  *
    3550                 :            :  * @param[in] item_flags
    3551                 :            :  *   Holds the items detected in this rule.
    3552                 :            :  * @param[in] action_flags
    3553                 :            :  *   Holds the actions detected until now.
    3554                 :            :  * @param[in] actions
    3555                 :            :  *   Pointer to the list of actions remaining in the flow rule.
    3556                 :            :  * @param[out] error
    3557                 :            :  *   Pointer to error structure.
    3558                 :            :  *
    3559                 :            :  * @return
    3560                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3561                 :            :  */
    3562                 :            : static int
    3563                 :          0 : flow_dv_validate_action_set_vlan_vid(uint64_t item_flags,
    3564                 :            :                                      uint64_t action_flags,
    3565                 :            :                                      const struct rte_flow_action actions[],
    3566                 :            :                                      struct rte_flow_error *error)
    3567                 :            : {
    3568                 :            :         const struct rte_flow_action *action = actions;
    3569                 :          0 :         const struct rte_flow_action_of_set_vlan_vid *conf = action->conf;
    3570                 :            : 
    3571   [ #  #  #  # ]:          0 :         if (rte_be_to_cpu_16(conf->vlan_vid) > 0xFFE)
    3572                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3573                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3574                 :            :                                           "VLAN VID value is too big");
    3575         [ #  # ]:          0 :         if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) &&
    3576         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
    3577                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3578                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3579                 :            :                                           "set VLAN VID action must follow push"
    3580                 :            :                                           " VLAN action or match on VLAN item");
    3581         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID)
    3582                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3583                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3584                 :            :                                           "Multiple VLAN VID modifications are "
    3585                 :            :                                           "not supported");
    3586         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
    3587                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3588                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3589                 :            :                                           "wrong action order, port_id should "
    3590                 :            :                                           "be after set VLAN VID");
    3591                 :            :         return 0;
    3592                 :            : }
    3593                 :            : 
    3594                 :            : /*
    3595                 :            :  * Validate the FLAG action.
    3596                 :            :  *
    3597                 :            :  * @param[in] dev
    3598                 :            :  *   Pointer to the rte_eth_dev structure.
    3599                 :            :  * @param[in] action_flags
    3600                 :            :  *   Holds the actions detected until now.
    3601                 :            :  * @param[in] attr
    3602                 :            :  *   Pointer to flow attributes
    3603                 :            :  * @param[out] error
    3604                 :            :  *   Pointer to error structure.
    3605                 :            :  *
    3606                 :            :  * @return
    3607                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3608                 :            :  */
    3609                 :            : static int
    3610                 :          0 : flow_dv_validate_action_flag(struct rte_eth_dev *dev,
    3611                 :            :                              uint64_t action_flags,
    3612                 :            :                              const struct rte_flow_attr *attr,
    3613                 :            :                              struct rte_flow_error *error)
    3614                 :            : {
    3615                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3616                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3617                 :            :         int ret;
    3618                 :            : 
    3619                 :            :         /* Fall back if no extended metadata register support. */
    3620         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
    3621                 :          0 :                 return mlx5_flow_validate_action_flag(action_flags, attr,
    3622                 :            :                                                       error);
    3623                 :            :         /* Extensive metadata mode requires registers. */
    3624         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3625                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3626                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3627                 :            :                                           "no metadata registers "
    3628                 :            :                                           "to support flag action");
    3629         [ #  # ]:          0 :         if (!(priv->sh->dv_mark_mask & MLX5_FLOW_MARK_DEFAULT))
    3630                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3631                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3632                 :            :                                           "extended metadata register"
    3633                 :            :                                           " isn't available");
    3634                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    3635         [ #  # ]:          0 :         if (ret < 0)
    3636                 :            :                 return ret;
    3637                 :            :         MLX5_ASSERT(ret > 0);
    3638         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_MARK)
    3639                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3640                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3641                 :            :                                           "can't mark and flag in same flow");
    3642         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_FLAG)
    3643                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3644                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3645                 :            :                                           "can't have 2 flag"
    3646                 :            :                                           " actions in same flow");
    3647                 :            :         return 0;
    3648                 :            : }
    3649                 :            : 
    3650                 :            : /**
    3651                 :            :  * Validate MARK action.
    3652                 :            :  *
    3653                 :            :  * @param[in] dev
    3654                 :            :  *   Pointer to the rte_eth_dev structure.
    3655                 :            :  * @param[in] action
    3656                 :            :  *   Pointer to action.
    3657                 :            :  * @param[in] action_flags
    3658                 :            :  *   Holds the actions detected until now.
    3659                 :            :  * @param[in] attr
    3660                 :            :  *   Pointer to flow attributes
    3661                 :            :  * @param[out] error
    3662                 :            :  *   Pointer to error structure.
    3663                 :            :  *
    3664                 :            :  * @return
    3665                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3666                 :            :  */
    3667                 :            : static int
    3668                 :          0 : flow_dv_validate_action_mark(struct rte_eth_dev *dev,
    3669                 :            :                              const struct rte_flow_action *action,
    3670                 :            :                              uint64_t action_flags,
    3671                 :            :                              const struct rte_flow_attr *attr,
    3672                 :            :                              struct rte_flow_error *error)
    3673                 :            : {
    3674                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3675                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3676         [ #  # ]:          0 :         const struct rte_flow_action_mark *mark = action->conf;
    3677                 :            :         int ret;
    3678                 :            : 
    3679         [ #  # ]:          0 :         if (is_tunnel_offload_active(dev))
    3680                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3681                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3682                 :            :                                           "no mark action "
    3683                 :            :                                           "if tunnel offload active");
    3684                 :            :         /* Fall back if no extended metadata register support. */
    3685         [ #  # ]:          0 :         if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY)
    3686                 :          0 :                 return mlx5_flow_validate_action_mark(dev, action, action_flags,
    3687                 :            :                                                       attr, error);
    3688                 :            :         /* Extensive metadata mode requires registers. */
    3689         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3690                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3691                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3692                 :            :                                           "no metadata registers "
    3693                 :            :                                           "to support mark action");
    3694         [ #  # ]:          0 :         if (!priv->sh->dv_mark_mask)
    3695                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3696                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3697                 :            :                                           "extended metadata register"
    3698                 :            :                                           " isn't available");
    3699                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error);
    3700         [ #  # ]:          0 :         if (ret < 0)
    3701                 :            :                 return ret;
    3702                 :            :         MLX5_ASSERT(ret > 0);
    3703         [ #  # ]:          0 :         if (!mark)
    3704                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3705                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3706                 :            :                                           "configuration cannot be null");
    3707         [ #  # ]:          0 :         if (mark->id >= (MLX5_FLOW_MARK_MAX & priv->sh->dv_mark_mask))
    3708                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3709                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    3710                 :          0 :                                           &mark->id,
    3711                 :            :                                           "mark id exceeds the limit");
    3712         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_FLAG)
    3713                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3714                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3715                 :            :                                           "can't flag and mark in same flow");
    3716         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_MARK)
    3717                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3718                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3719                 :            :                                           "can't have 2 mark actions in same"
    3720                 :            :                                           " flow");
    3721                 :            :         return 0;
    3722                 :            : }
    3723                 :            : 
    3724                 :            : /**
    3725                 :            :  * Validate SET_META action.
    3726                 :            :  *
    3727                 :            :  * @param[in] dev
    3728                 :            :  *   Pointer to the rte_eth_dev structure.
    3729                 :            :  * @param[in] action
    3730                 :            :  *   Pointer to the action structure.
    3731                 :            :  * @param[in] action_flags
    3732                 :            :  *   Holds the actions detected until now.
    3733                 :            :  * @param[in] attr
    3734                 :            :  *   Pointer to flow attributes
    3735                 :            :  * @param[out] error
    3736                 :            :  *   Pointer to error structure.
    3737                 :            :  *
    3738                 :            :  * @return
    3739                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3740                 :            :  */
    3741                 :            : static int
    3742                 :          0 : flow_dv_validate_action_set_meta(struct rte_eth_dev *dev,
    3743                 :            :                                  const struct rte_flow_action *action,
    3744                 :            :                                  uint64_t action_flags __rte_unused,
    3745                 :            :                                  const struct rte_flow_attr *attr,
    3746                 :            :                                  struct rte_flow_error *error)
    3747                 :            : {
    3748                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3749                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    3750                 :            :         const struct rte_flow_action_set_meta *conf;
    3751                 :            :         uint32_t nic_mask = UINT32_MAX;
    3752                 :            :         int reg;
    3753                 :            : 
    3754   [ #  #  #  # ]:          0 :         if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    3755                 :          0 :             !mlx5_flow_ext_mreg_supported(dev))
    3756                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3757                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3758                 :            :                                           "extended metadata register"
    3759                 :            :                                           " isn't supported");
    3760                 :          0 :         reg = flow_dv_get_metadata_reg(dev, attr, error);
    3761         [ #  # ]:          0 :         if (reg < 0)
    3762                 :            :                 return reg;
    3763         [ #  # ]:          0 :         if (reg == REG_NON)
    3764                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3765                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3766                 :            :                                           "unavailable extended metadata register");
    3767         [ #  # ]:          0 :         if (reg != REG_A && reg != REG_B) {
    3768                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
    3769                 :            : 
    3770                 :          0 :                 nic_mask = priv->sh->dv_meta_mask;
    3771                 :            :         }
    3772         [ #  # ]:          0 :         if (!(action->conf))
    3773                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3774                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3775                 :            :                                           "configuration cannot be null");
    3776                 :            :         conf = (const struct rte_flow_action_set_meta *)action->conf;
    3777         [ #  # ]:          0 :         if (!conf->mask)
    3778                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3779                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3780                 :            :                                           "zero mask doesn't have any effect");
    3781         [ #  # ]:          0 :         if (conf->mask & ~nic_mask)
    3782                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3783                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3784                 :            :                                           "meta data must be within reg C0");
    3785                 :            :         return 0;
    3786                 :            : }
    3787                 :            : 
    3788                 :            : /**
    3789                 :            :  * Validate SET_TAG action.
    3790                 :            :  *
    3791                 :            :  * @param[in] dev
    3792                 :            :  *   Pointer to the rte_eth_dev structure.
    3793                 :            :  * @param[in] action
    3794                 :            :  *   Pointer to the action structure.
    3795                 :            :  * @param[in] action_flags
    3796                 :            :  *   Holds the actions detected until now.
    3797                 :            :  * @param[in] attr
    3798                 :            :  *   Pointer to flow attributes
    3799                 :            :  * @param[out] error
    3800                 :            :  *   Pointer to error structure.
    3801                 :            :  *
    3802                 :            :  * @return
    3803                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3804                 :            :  */
    3805                 :            : static int
    3806                 :          0 : flow_dv_validate_action_set_tag(struct rte_eth_dev *dev,
    3807                 :            :                                 const struct rte_flow_action *action,
    3808                 :            :                                 uint64_t action_flags,
    3809                 :            :                                 const struct rte_flow_attr *attr,
    3810                 :            :                                 struct rte_flow_error *error)
    3811                 :            : {
    3812                 :            :         const struct rte_flow_action_set_tag *conf;
    3813                 :            :         const uint64_t terminal_action_flags =
    3814                 :            :                 MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
    3815                 :            :                 MLX5_FLOW_ACTION_RSS;
    3816                 :            :         int ret;
    3817                 :            : 
    3818         [ #  # ]:          0 :         if (!mlx5_flow_ext_mreg_supported(dev))
    3819                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3820                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3821                 :            :                                           "extensive metadata register"
    3822                 :            :                                           " isn't supported");
    3823         [ #  # ]:          0 :         if (!(action->conf))
    3824                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3825                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3826                 :            :                                           "configuration cannot be null");
    3827                 :            :         conf = (const struct rte_flow_action_set_tag *)action->conf;
    3828         [ #  # ]:          0 :         if (!conf->mask)
    3829                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3830                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3831                 :            :                                           "zero mask doesn't have any effect");
    3832                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, conf->index, error);
    3833         [ #  # ]:          0 :         if (ret < 0)
    3834                 :            :                 return ret;
    3835   [ #  #  #  # ]:          0 :         if (attr->ingress && (action_flags & terminal_action_flags))
    3836                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3837                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3838                 :            :                                           "set_tag has no effect"
    3839                 :            :                                           " with terminal actions");
    3840                 :            :         return 0;
    3841                 :            : }
    3842                 :            : 
    3843                 :            : /**
    3844                 :            :  * Indicates whether ASO aging is supported.
    3845                 :            :  *
    3846                 :            :  * @param[in] priv
    3847                 :            :  *   Pointer to device private context structure.
    3848                 :            :  * @param[in] root
    3849                 :            :  *   Whether action is on root table.
    3850                 :            :  *
    3851                 :            :  * @return
    3852                 :            :  *   True when ASO aging is supported, false otherwise.
    3853                 :            :  */
    3854                 :            : static inline bool
    3855                 :            : flow_hit_aso_supported(const struct mlx5_priv *priv, bool root)
    3856                 :            : {
    3857                 :            :         MLX5_ASSERT(priv);
    3858   [ #  #  #  #  :          0 :         return (priv->sh->flow_hit_aso_en && !root);
          #  #  #  #  #  
                      # ]
    3859                 :            : }
    3860                 :            : 
    3861                 :            : /**
    3862                 :            :  * Validate count action.
    3863                 :            :  *
    3864                 :            :  * @param[in] dev
    3865                 :            :  *   Pointer to rte_eth_dev structure.
    3866                 :            :  * @param[in] shared
    3867                 :            :  *   Indicator if action is shared.
    3868                 :            :  * @param[in] action_flags
    3869                 :            :  *   Holds the actions detected until now.
    3870                 :            :  * @param[in] root
    3871                 :            :  *   Whether action is on root table.
    3872                 :            :  * @param[out] error
    3873                 :            :  *   Pointer to error structure.
    3874                 :            :  *
    3875                 :            :  * @return
    3876                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3877                 :            :  */
    3878                 :            : static int
    3879                 :          0 : flow_dv_validate_action_count(struct rte_eth_dev *dev, bool shared,
    3880                 :            :                               uint64_t action_flags,
    3881                 :            :                               bool root,
    3882                 :            :                               struct rte_flow_error *error)
    3883                 :            : {
    3884                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    3885                 :            : 
    3886         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
    3887                 :          0 :                 goto notsup_err;
    3888         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_COUNT)
    3889                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3890                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3891                 :            :                                           "duplicate count actions set");
    3892   [ #  #  #  #  :          0 :         if (shared && (action_flags & MLX5_FLOW_ACTION_AGE) &&
                   #  # ]
    3893                 :            :             !flow_hit_aso_supported(priv, root))
    3894                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3895                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3896                 :            :                                           "old age and indirect count combination is not supported");
    3897                 :            : #ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
    3898                 :            :         return 0;
    3899                 :            : #endif
    3900                 :            : notsup_err:
    3901                 :          0 :         return rte_flow_error_set
    3902                 :            :                       (error, ENOTSUP,
    3903                 :            :                        RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    3904                 :            :                        NULL,
    3905                 :            :                        "count action not supported");
    3906                 :            : }
    3907                 :            : 
    3908                 :            : /**
    3909                 :            :  * Validate the L2 encap action.
    3910                 :            :  *
    3911                 :            :  * @param[in] dev
    3912                 :            :  *   Pointer to the rte_eth_dev structure.
    3913                 :            :  * @param[in] action_flags
    3914                 :            :  *   Holds the actions detected until now.
    3915                 :            :  * @param[in] action
    3916                 :            :  *   Pointer to the action structure.
    3917                 :            :  * @param[in] attr
    3918                 :            :  *   Pointer to flow attributes.
    3919                 :            :  * @param[out] error
    3920                 :            :  *   Pointer to error structure.
    3921                 :            :  *
    3922                 :            :  * @return
    3923                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3924                 :            :  */
    3925                 :            : int
    3926                 :          0 : mlx5_flow_dv_validate_action_l2_encap(struct rte_eth_dev *dev,
    3927                 :            :                                       uint64_t action_flags,
    3928                 :            :                                       const struct rte_flow_action *action,
    3929                 :            :                                       const struct rte_flow_attr *attr,
    3930                 :            :                                       struct rte_flow_error *error)
    3931                 :            : {
    3932                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3933                 :            : 
    3934         [ #  # ]:          0 :         if (!(action->conf))
    3935                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3936                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    3937                 :            :                                           "configuration cannot be null");
    3938         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    3939                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3940                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3941                 :            :                                           "can only have a single encap action "
    3942                 :            :                                           "in a flow");
    3943   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    3944                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3945                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3946                 :            :                                           "encap action for VF representor "
    3947                 :            :                                           "not supported on NIC table");
    3948                 :            :         return 0;
    3949                 :            : }
    3950                 :            : 
    3951                 :            : /**
    3952                 :            :  * Validate a decap action.
    3953                 :            :  *
    3954                 :            :  * @param[in] dev
    3955                 :            :  *   Pointer to the rte_eth_dev structure.
    3956                 :            :  * @param[in] action_flags
    3957                 :            :  *   Holds the actions detected until now.
    3958                 :            :  * @param[in] action
    3959                 :            :  *   Pointer to the action structure.
    3960                 :            :  * @param[in] item_flags
    3961                 :            :  *   Holds the items detected.
    3962                 :            :  * @param[in] attr
    3963                 :            :  *   Pointer to flow attributes
    3964                 :            :  * @param[out] error
    3965                 :            :  *   Pointer to error structure.
    3966                 :            :  *
    3967                 :            :  * @return
    3968                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    3969                 :            :  */
    3970                 :            : int
    3971                 :          0 : mlx5_flow_dv_validate_action_decap(struct rte_eth_dev *dev,
    3972                 :            :                                    uint64_t action_flags,
    3973                 :            :                                    const struct rte_flow_action *action,
    3974                 :            :                                    const uint64_t item_flags,
    3975                 :            :                                    const struct rte_flow_attr *attr,
    3976                 :            :                                    struct rte_flow_error *error)
    3977                 :            : {
    3978                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    3979                 :            : 
    3980         [ #  # ]:          0 :         if (priv->sh->cdev->config.hca_attr.scatter_fcs_w_decap_disable &&
    3981         [ #  # ]:          0 :             !priv->sh->config.decap_en)
    3982                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3983                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3984                 :            :                                           "decap is not enabled");
    3985         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_XCAP_ACTIONS)
    3986                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3987                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3988         [ #  # ]:          0 :                                           action_flags &
    3989                 :            :                                           MLX5_FLOW_ACTION_DECAP ? "can only "
    3990                 :            :                                           "have a single decap action" : "decap "
    3991                 :            :                                           "after encap is not supported");
    3992         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)
    3993                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3994                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    3995                 :            :                                           "can't have decap action after"
    3996                 :            :                                           " modify action");
    3997         [ #  # ]:          0 :         if (attr->egress)
    3998                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3999                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
    4000                 :            :                                           NULL,
    4001                 :            :                                           "decap action not supported for "
    4002                 :            :                                           "egress");
    4003   [ #  #  #  # ]:          0 :         if (!attr->transfer && priv->representor)
    4004                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4005                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4006                 :            :                                           "decap action for VF representor "
    4007                 :            :                                           "not supported on NIC table");
    4008         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP &&
    4009         [ #  # ]:          0 :             !(item_flags & MLX5_FLOW_LAYER_VXLAN))
    4010                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4011                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4012                 :            :                                 "VXLAN item should be present for VXLAN decap");
    4013                 :            :         return 0;
    4014                 :            : }
    4015                 :            : 
    4016                 :            : const struct rte_flow_action_raw_decap empty_decap = {.data = NULL, .size = 0,};
    4017                 :            : 
    4018                 :            : /**
    4019                 :            :  * Validate the raw encap and decap actions.
    4020                 :            :  *
    4021                 :            :  * @param[in] dev
    4022                 :            :  *   Pointer to the rte_eth_dev structure.
    4023                 :            :  * @param[in] decap
    4024                 :            :  *   Pointer to the decap action.
    4025                 :            :  * @param[in] encap
    4026                 :            :  *   Pointer to the encap action.
    4027                 :            :  * @param[in] attr
    4028                 :            :  *   Pointer to flow attributes
    4029                 :            :  * @param[in/out] action_flags
    4030                 :            :  *   Holds the actions detected until now.
    4031                 :            :  * @param[out] actions_n
    4032                 :            :  *   pointer to the number of actions counter.
    4033                 :            :  * @param[in] action
    4034                 :            :  *   Pointer to the action structure.
    4035                 :            :  * @param[in] item_flags
    4036                 :            :  *   Holds the items detected.
    4037                 :            :  * @param[out] error
    4038                 :            :  *   Pointer to error structure.
    4039                 :            :  *
    4040                 :            :  * @return
    4041                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4042                 :            :  */
    4043                 :            : int
    4044                 :          0 : mlx5_flow_dv_validate_action_raw_encap_decap
    4045                 :            :         (struct rte_eth_dev *dev,
    4046                 :            :          const struct rte_flow_action_raw_decap *decap,
    4047                 :            :          const struct rte_flow_action_raw_encap *encap,
    4048                 :            :          const struct rte_flow_attr *attr, uint64_t *action_flags,
    4049                 :            :          int *actions_n, const struct rte_flow_action *action,
    4050                 :            :          uint64_t item_flags, struct rte_flow_error *error)
    4051                 :            : {
    4052                 :          0 :         const struct mlx5_priv *priv = dev->data->dev_private;
    4053                 :            :         int ret;
    4054                 :            : 
    4055         [ #  # ]:          0 :         if (encap) {
    4056         [ #  # ]:          0 :                 if (!mlx5_hws_active(dev)) {
    4057   [ #  #  #  # ]:          0 :                         if (!encap->size || !encap->data)
    4058                 :          0 :                                 return rte_flow_error_set
    4059                 :            :                                         (error, EINVAL,
    4060                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION, NULL, "raw encap data cannot be empty");
    4061                 :            :                 } else {
    4062         [ #  # ]:          0 :                         if (!encap->size)
    4063                 :          0 :                                 return rte_flow_error_set
    4064                 :            :                                         (error, EINVAL,
    4065                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION, NULL, "raw encap size cannot be 0");
    4066                 :            :                 }
    4067                 :            :         }
    4068         [ #  # ]:          0 :         if (decap && encap) {
    4069         [ #  # ]:          0 :                 if (decap->size <= MLX5_ENCAPSULATION_DECISION_SIZE &&
    4070         [ #  # ]:          0 :                     encap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
    4071                 :            :                         /* L3 encap. */
    4072                 :            :                         decap = NULL;
    4073         [ #  # ]:          0 :                 else if (encap->size <=
    4074         [ #  # ]:          0 :                            MLX5_ENCAPSULATION_DECISION_SIZE &&
    4075                 :            :                            decap->size >
    4076                 :            :                            MLX5_ENCAPSULATION_DECISION_SIZE)
    4077                 :            :                         /* L3 decap. */
    4078                 :            :                         encap = NULL;
    4079         [ #  # ]:          0 :                 else if (encap->size >
    4080         [ #  # ]:          0 :                            MLX5_ENCAPSULATION_DECISION_SIZE &&
    4081                 :            :                            decap->size >
    4082                 :            :                            MLX5_ENCAPSULATION_DECISION_SIZE)
    4083                 :            :                         /* 2 L2 actions: encap and decap. */
    4084                 :            :                         ;
    4085                 :            :                 else
    4086                 :          0 :                         return rte_flow_error_set(error,
    4087                 :            :                                 ENOTSUP,
    4088                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4089                 :            :                                 NULL, "unsupported too small "
    4090                 :            :                                 "raw decap and too small raw "
    4091                 :            :                                 "encap combination");
    4092                 :            :         }
    4093         [ #  # ]:          0 :         if (decap) {
    4094                 :          0 :                 ret = mlx5_flow_dv_validate_action_decap(dev, *action_flags,
    4095                 :            :                                                          action,
    4096                 :            :                                                          item_flags, attr,
    4097                 :            :                                                          error);
    4098         [ #  # ]:          0 :                 if (ret < 0)
    4099                 :            :                         return ret;
    4100                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_DECAP;
    4101                 :          0 :                 ++(*actions_n);
    4102                 :            :         }
    4103         [ #  # ]:          0 :         if (encap) {
    4104         [ #  # ]:          0 :                 if (encap->size <= MLX5_ENCAPSULATION_DECISION_SIZE)
    4105                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    4106                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4107                 :            :                                                   NULL,
    4108                 :            :                                                   "small raw encap size");
    4109         [ #  # ]:          0 :                 if (*action_flags & MLX5_FLOW_ACTION_ENCAP)
    4110                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4111                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4112                 :            :                                                   NULL,
    4113                 :            :                                                   "more than one encap action");
    4114   [ #  #  #  # ]:          0 :                 if (!attr->transfer && priv->representor)
    4115                 :          0 :                         return rte_flow_error_set
    4116                 :            :                                         (error, ENOTSUP,
    4117                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4118                 :            :                                          "encap action for VF representor "
    4119                 :            :                                          "not supported on NIC table");
    4120                 :          0 :                 *action_flags |= MLX5_FLOW_ACTION_ENCAP;
    4121                 :          0 :                 ++(*actions_n);
    4122                 :            :         }
    4123                 :            :         return 0;
    4124                 :            : }
    4125                 :            : 
    4126                 :            : /*
    4127                 :            :  * Validate the ASO CT action.
    4128                 :            :  *
    4129                 :            :  * @param[in] dev
    4130                 :            :  *   Pointer to the rte_eth_dev structure.
    4131                 :            :  * @param[in] action_flags
    4132                 :            :  *   Holds the actions detected until now.
    4133                 :            :  * @param[in] item_flags
    4134                 :            :  *   The items found in this flow rule.
    4135                 :            :  * @param root
    4136                 :            :  *   Whether action is on root table.
    4137                 :            :  * @param[out] error
    4138                 :            :  *   Pointer to error structure.
    4139                 :            :  *
    4140                 :            :  * @return
    4141                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4142                 :            :  */
    4143                 :            : int
    4144                 :          0 : mlx5_flow_dv_validate_action_aso_ct(struct rte_eth_dev *dev,
    4145                 :            :                                     uint64_t action_flags,
    4146                 :            :                                     uint64_t item_flags,
    4147                 :            :                                     bool root,
    4148                 :            :                                     struct rte_flow_error *error)
    4149                 :            : {
    4150                 :            :         RTE_SET_USED(dev);
    4151                 :            : 
    4152         [ #  # ]:          0 :         if (root)
    4153                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4154                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4155                 :            :                                           NULL,
    4156                 :            :                                           "Only support non-root table");
    4157         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_FATE_ACTIONS)
    4158                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4159                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4160                 :            :                                           "CT cannot follow a fate action");
    4161         [ #  # ]:          0 :         if ((action_flags & MLX5_FLOW_ACTION_METER) ||
    4162                 :            :             (action_flags & MLX5_FLOW_ACTION_AGE)) {
    4163         [ #  # ]:          0 :                 if (!mlx5_hws_active(dev))
    4164                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4165                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4166                 :            :                                                   NULL, "Only one ASO action is supported");
    4167                 :            :         }
    4168         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    4169                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4170                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4171                 :            :                                           "Encap cannot exist before CT");
    4172         [ #  # ]:          0 :         if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP))
    4173                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4174                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4175                 :            :                                           "Not a outer TCP packet");
    4176                 :            :         return 0;
    4177                 :            : }
    4178                 :            : 
    4179                 :            : /**
    4180                 :            :  * Validate METER_COLOR item.
    4181                 :            :  *
    4182                 :            :  * @param[in] dev
    4183                 :            :  *   Pointer to the rte_eth_dev structure.
    4184                 :            :  * @param[in] item
    4185                 :            :  *   Item specification.
    4186                 :            :  * @param[in] attr
    4187                 :            :  *   Attributes of flow that includes this item.
    4188                 :            :  * @param[out] error
    4189                 :            :  *   Pointer to error structure.
    4190                 :            :  *
    4191                 :            :  * @return
    4192                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4193                 :            :  */
    4194                 :            : static int
    4195                 :          0 : flow_dv_validate_item_meter_color(struct rte_eth_dev *dev,
    4196                 :            :                            const struct rte_flow_item *item,
    4197                 :            :                            const struct rte_flow_attr *attr __rte_unused,
    4198                 :            :                            struct rte_flow_error *error)
    4199                 :            : {
    4200                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4201                 :          0 :         const struct rte_flow_item_meter_color *spec = item->spec;
    4202                 :          0 :         const struct rte_flow_item_meter_color *mask = item->mask;
    4203                 :          0 :         struct rte_flow_item_meter_color nic_mask = {
    4204                 :            :                 .color = RTE_COLORS
    4205                 :            :         };
    4206                 :            :         int ret;
    4207                 :            : 
    4208         [ #  # ]:          0 :         if (priv->sh->registers.aso_reg == REG_NON)
    4209                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4210                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    4211                 :            :                                           "meter color register"
    4212                 :            :                                           " isn't available");
    4213                 :          0 :         ret = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, error);
    4214         [ #  # ]:          0 :         if (ret < 0)
    4215                 :            :                 return ret;
    4216         [ #  # ]:          0 :         if (!spec)
    4217                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4218                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4219                 :          0 :                                           item->spec,
    4220                 :            :                                           "data cannot be empty");
    4221         [ #  # ]:          0 :         if (spec->color > RTE_COLORS)
    4222                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4223                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    4224                 :          0 :                                           &spec->color,
    4225                 :            :                                           "meter color is invalid");
    4226         [ #  # ]:          0 :         if (!mask)
    4227                 :            :                 mask = &rte_flow_item_meter_color_mask;
    4228         [ #  # ]:          0 :         if (!mask->color)
    4229                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4230                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    4231                 :            :                                         "mask cannot be zero");
    4232                 :            : 
    4233                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    4234                 :            :                                 (const uint8_t *)&nic_mask,
    4235                 :            :                                 sizeof(struct rte_flow_item_meter_color),
    4236                 :            :                                 MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    4237                 :            :         if (ret < 0)
    4238                 :            :                 return ret;
    4239                 :            :         return 0;
    4240                 :            : }
    4241                 :            : 
    4242                 :            : /**
    4243                 :            :  * Validate aggregated affinity item.
    4244                 :            :  *
    4245                 :            :  * @param[in] dev
    4246                 :            :  *   Pointer to the rte_eth_dev structure.
    4247                 :            :  * @param[in] item
    4248                 :            :  *   Item specification.
    4249                 :            :  * @param[in] attr
    4250                 :            :  *   Attributes of flow that includes this item.
    4251                 :            :  * @param[out] error
    4252                 :            :  *   Pointer to error structure.
    4253                 :            :  *
    4254                 :            :  * @return
    4255                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4256                 :            :  */
    4257                 :            : static int
    4258                 :          0 : flow_dv_validate_item_aggr_affinity(struct rte_eth_dev *dev,
    4259                 :            :                                    const struct rte_flow_item *item,
    4260                 :            :                                    const struct rte_flow_attr *attr,
    4261                 :            :                                    struct rte_flow_error *error)
    4262                 :            : {
    4263                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4264                 :          0 :         const struct rte_flow_item_aggr_affinity *spec = item->spec;
    4265                 :          0 :         const struct rte_flow_item_aggr_affinity *mask = item->mask;
    4266                 :          0 :         struct rte_flow_item_aggr_affinity nic_mask = {
    4267                 :            :                 .affinity = UINT8_MAX
    4268                 :            :         };
    4269                 :            :         int ret;
    4270                 :            : 
    4271         [ #  # ]:          0 :         if (!priv->sh->lag_rx_port_affinity_en)
    4272                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4273                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    4274                 :            :                                           "Unsupported aggregated affinity with Older FW");
    4275   [ #  #  #  #  :          0 :         if ((attr->transfer && priv->fdb_def_rule) ||
                   #  # ]
    4276         [ #  # ]:          0 :             attr->egress || attr->group)
    4277                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4278                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4279                 :            :                                           item->spec,
    4280                 :            :                                           "aggregated affinity is not supported with egress or FDB on non root table");
    4281         [ #  # ]:          0 :         if (!spec)
    4282                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4283                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4284                 :            :                                           item->spec,
    4285                 :            :                                           "data cannot be empty");
    4286         [ #  # ]:          0 :         if (spec->affinity == 0)
    4287                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4288                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4289                 :            :                                           item->spec,
    4290                 :            :                                           "zero affinity number not supported");
    4291         [ #  # ]:          0 :         if (spec->affinity > priv->num_lag_ports)
    4292                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4293                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    4294                 :            :                                           item->spec,
    4295                 :            :                                           "exceed max affinity number in lag ports");
    4296         [ #  # ]:          0 :         if (!mask)
    4297                 :            :                 mask = &rte_flow_item_aggr_affinity_mask;
    4298         [ #  # ]:          0 :         if (!mask->affinity)
    4299                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4300                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    4301                 :            :                                           "mask cannot be zero");
    4302                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    4303                 :            :                                 (const uint8_t *)&nic_mask,
    4304                 :            :                                 sizeof(struct rte_flow_item_aggr_affinity),
    4305                 :            :                                 MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    4306                 :            :         if (ret < 0)
    4307                 :            :                 return ret;
    4308                 :            :         return 0;
    4309                 :            : }
    4310                 :            : 
    4311                 :            : int
    4312                 :          0 : mlx5_flow_encap_decap_match_cb(void *tool_ctx __rte_unused,
    4313                 :            :                                struct mlx5_list_entry *entry, void *cb_ctx)
    4314                 :            : {
    4315                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4316                 :          0 :         struct mlx5_flow_dv_encap_decap_resource *ctx_resource = ctx->data;
    4317                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
    4318                 :            : 
    4319                 :            :         resource = container_of(entry, struct mlx5_flow_dv_encap_decap_resource,
    4320                 :            :                                 entry);
    4321         [ #  # ]:          0 :         if (resource->reformat_type == ctx_resource->reformat_type &&
    4322                 :          0 :             resource->ft_type == ctx_resource->ft_type &&
    4323         [ #  # ]:          0 :             resource->flags == ctx_resource->flags &&
    4324         [ #  # ]:          0 :             resource->size == ctx_resource->size &&
    4325                 :          0 :             !memcmp((const void *)resource->buf,
    4326         [ #  # ]:          0 :                     (const void *)ctx_resource->buf,
    4327                 :            :                     resource->size))
    4328                 :          0 :                 return 0;
    4329                 :            :         return -1;
    4330                 :            : }
    4331                 :            : 
    4332                 :            : struct mlx5_list_entry *
    4333                 :          0 : mlx5_flow_encap_decap_create_cb(void *tool_ctx, void *cb_ctx)
    4334                 :            : {
    4335                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4336                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4337                 :            :         struct mlx5dv_dr_domain *domain;
    4338                 :          0 :         struct mlx5_flow_dv_encap_decap_resource *ctx_resource = ctx->data;
    4339                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
    4340                 :            :         uint32_t idx;
    4341                 :            :         int ret = 0;
    4342                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    4343                 :            :         struct mlx5dr_action_reformat_header hdr;
    4344                 :            : #endif
    4345                 :            : 
    4346                 :            :         /* Register new encap/decap resource. */
    4347                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], &idx);
    4348         [ #  # ]:          0 :         if (!resource) {
    4349                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4350                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4351                 :            :                                    "cannot allocate resource memory");
    4352                 :          0 :                 return NULL;
    4353                 :            :         }
    4354                 :          0 :         *resource = *ctx_resource;
    4355         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2) {
    4356                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    4357                 :          0 :                 hdr.sz = ctx_resource->size;
    4358                 :          0 :                 hdr.data = ctx_resource->buf;
    4359                 :          0 :                 resource->action = mlx5dr_action_create_reformat
    4360                 :          0 :                 (ctx->data2, (enum mlx5dr_action_type)ctx_resource->reformat_type, 1,
    4361                 :          0 :                         &hdr, 0, ctx_resource->flags);
    4362         [ #  # ]:          0 :                 if (!resource->action)
    4363                 :            :                         ret = -1;
    4364                 :            : #else
    4365                 :            :                 ret = -1;
    4366                 :            : #endif
    4367                 :            :         } else {
    4368         [ #  # ]:          0 :                 if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    4369                 :          0 :                         domain = sh->fdb_domain;
    4370         [ #  # ]:          0 :                 else if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
    4371                 :          0 :                         domain = sh->rx_domain;
    4372                 :            :                 else
    4373                 :          0 :                         domain = sh->tx_domain;
    4374         [ #  # ]:          0 :                 ret = mlx5_flow_os_create_flow_action_packet_reformat(sh->cdev->ctx,
    4375                 :            :                         domain, resource,
    4376                 :            :                 &resource->action);
    4377                 :            :         }
    4378                 :            :         if (ret) {
    4379                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], idx);
    4380                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4381                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    4382                 :            :                                    NULL, "cannot create action");
    4383                 :          0 :                 return NULL;
    4384                 :            :         }
    4385                 :          0 :         resource->idx = idx;
    4386                 :          0 :         return &resource->entry;
    4387                 :            : }
    4388                 :            : 
    4389                 :            : struct mlx5_list_entry *
    4390                 :          0 : mlx5_flow_encap_decap_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
    4391                 :            :                                void *cb_ctx)
    4392                 :            : {
    4393                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4394                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4395                 :            :         struct mlx5_flow_dv_encap_decap_resource *cache_resource;
    4396                 :            :         struct mlx5_flow_dv_encap_decap_resource *old_resource;
    4397                 :            :         uint32_t idx;
    4398                 :            : 
    4399                 :          0 :         cache_resource = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
    4400                 :            :                                            &idx);
    4401         [ #  # ]:          0 :         if (!cache_resource) {
    4402                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4403                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4404                 :            :                                    "cannot allocate resource memory");
    4405                 :          0 :                 return NULL;
    4406                 :            :         }
    4407                 :            :         old_resource = container_of(oentry, typeof(*old_resource), entry);
    4408                 :            :         memcpy(cache_resource, old_resource, sizeof(*cache_resource));
    4409                 :          0 :         cache_resource->idx = idx;
    4410                 :          0 :         return &cache_resource->entry;
    4411                 :            : }
    4412                 :            : 
    4413                 :            : void
    4414                 :          0 : mlx5_flow_encap_decap_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4415                 :            : {
    4416                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4417                 :            :         struct mlx5_flow_dv_encap_decap_resource *res =
    4418                 :            :                                        container_of(entry, typeof(*res), entry);
    4419                 :            : 
    4420                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx);
    4421                 :          0 : }
    4422                 :            : 
    4423                 :            : int
    4424                 :          0 : mlx5_flow_encap_decap_resource_register(struct rte_eth_dev *dev,
    4425                 :            :                                         struct mlx5_flow_dv_encap_decap_resource *resource,
    4426                 :            :                                         bool is_root,
    4427                 :            :                                         struct mlx5_flow_dv_encap_decap_resource **encap_decap,
    4428                 :            :                                         struct rte_flow_error *error)
    4429                 :            : {
    4430                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4431                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
    4432                 :            :         struct mlx5_list_entry *entry;
    4433                 :            :         union {
    4434                 :            :                 struct {
    4435                 :            :                         uint32_t ft_type:8;
    4436                 :            :                         uint32_t refmt_type:8;
    4437                 :            :                         /*
    4438                 :            :                          * Header reformat actions can be shared between
    4439                 :            :                          * non-root tables. One bit to indicate non-root
    4440                 :            :                          * table or not.
    4441                 :            :                          */
    4442                 :            :                         uint32_t is_root:1;
    4443                 :            :                         uint32_t reserve:15;
    4444                 :            :                 };
    4445                 :            :                 uint32_t v32;
    4446                 :          0 :         } encap_decap_key = {
    4447                 :            :                 {
    4448                 :          0 :                         .ft_type = resource->ft_type,
    4449                 :          0 :                         .refmt_type = resource->reformat_type,
    4450                 :            :                         .is_root = is_root,
    4451                 :            :                         .reserve = 0,
    4452                 :            :                 }
    4453                 :            :         };
    4454                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4455                 :            :                 .error = error,
    4456                 :            :                 .data = resource,
    4457                 :          0 :                 .data2 = priv->dr_ctx,
    4458                 :            :         };
    4459                 :            :         struct mlx5_hlist *encaps_decaps;
    4460                 :            :         uint64_t key64;
    4461                 :            : 
    4462                 :          0 :         encaps_decaps = flow_dv_hlist_prepare(sh, &sh->encaps_decaps,
    4463                 :            :                                 "encaps_decaps",
    4464                 :            :                                 MLX5_FLOW_ENCAP_DECAP_HTABLE_SZ,
    4465                 :            :                                 true, true, sh,
    4466                 :            :                                 mlx5_flow_encap_decap_create_cb,
    4467                 :            :                                 mlx5_flow_encap_decap_match_cb,
    4468                 :            :                                 mlx5_flow_encap_decap_remove_cb,
    4469                 :            :                                 mlx5_flow_encap_decap_clone_cb,
    4470                 :            :                                 mlx5_flow_encap_decap_clone_free_cb,
    4471                 :            :                                 error);
    4472         [ #  # ]:          0 :         if (unlikely(!encaps_decaps))
    4473                 :          0 :                 return -rte_errno;
    4474                 :          0 :         key64 =  __rte_raw_cksum(&encap_decap_key.v32,
    4475                 :            :                                  sizeof(encap_decap_key.v32), 0);
    4476         [ #  # ]:          0 :         if (resource->reformat_type !=
    4477                 :          0 :             MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2 &&
    4478         [ #  # ]:          0 :             resource->size)
    4479                 :          0 :                 key64 = __rte_raw_cksum(resource->buf, resource->size, key64);
    4480                 :          0 :         entry = mlx5_hlist_register(encaps_decaps, key64, &ctx);
    4481         [ #  # ]:          0 :         if (!entry)
    4482                 :          0 :                 return -rte_errno;
    4483                 :          0 :         *encap_decap = container_of(entry, typeof(*resource), entry);
    4484                 :          0 :         return 0;
    4485                 :            : }
    4486                 :            : 
    4487                 :            : /**
    4488                 :            :  * Find existing encap/decap resource or create and register a new one.
    4489                 :            :  *
    4490                 :            :  * @param[in, out] dev
    4491                 :            :  *   Pointer to rte_eth_dev structure.
    4492                 :            :  * @param[in, out] resource
    4493                 :            :  *   Pointer to encap/decap resource.
    4494                 :            :  * @param[in, out] dev_flow
    4495                 :            :  *   Pointer to the dev_flow.
    4496                 :            :  * @param[out] error
    4497                 :            :  *   pointer to error structure.
    4498                 :            :  *
    4499                 :            :  * @return
    4500                 :            :  *   0 on success otherwise -errno and errno is set.
    4501                 :            :  */
    4502                 :            : static int
    4503                 :          0 : flow_dv_encap_decap_resource_register
    4504                 :            :                         (struct rte_eth_dev *dev,
    4505                 :            :                          struct mlx5_flow_dv_encap_decap_resource *resource,
    4506                 :            :                          struct mlx5_flow *dev_flow,
    4507                 :            :                          struct rte_flow_error *error)
    4508                 :            : {
    4509                 :            :         int ret;
    4510                 :            : 
    4511                 :          0 :         resource->flags = dev_flow->dv.group ? 0 : 1;
    4512                 :          0 :         ret = mlx5_flow_encap_decap_resource_register(dev, resource, !!dev_flow->dv.group,
    4513                 :            :                                                       &dev_flow->dv.encap_decap, error);
    4514         [ #  # ]:          0 :         if (ret)
    4515                 :            :                 return ret;
    4516                 :          0 :         dev_flow->handle->dvh.rix_encap_decap = dev_flow->dv.encap_decap->idx;
    4517                 :          0 :         return 0;
    4518                 :            : }
    4519                 :            : 
    4520                 :            : /**
    4521                 :            :  * Find existing table jump resource or create and register a new one.
    4522                 :            :  *
    4523                 :            :  * @param[in, out] dev
    4524                 :            :  *   Pointer to rte_eth_dev structure.
    4525                 :            :  * @param[in, out] tbl
    4526                 :            :  *   Pointer to flow table resource.
    4527                 :            :  * @parm[in, out] dev_flow
    4528                 :            :  *   Pointer to the dev_flow.
    4529                 :            :  * @param[out] error
    4530                 :            :  *   pointer to error structure.
    4531                 :            :  *
    4532                 :            :  * @return
    4533                 :            :  *   0 on success otherwise -errno and errno is set.
    4534                 :            :  */
    4535                 :            : static int
    4536                 :            : flow_dv_jump_tbl_resource_register
    4537                 :            :                         (struct rte_eth_dev *dev __rte_unused,
    4538                 :            :                          struct mlx5_flow_tbl_resource *tbl,
    4539                 :            :                          struct mlx5_flow *dev_flow,
    4540                 :            :                          struct rte_flow_error *error __rte_unused)
    4541                 :            : {
    4542                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
    4543                 :          0 :                 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
    4544                 :            : 
    4545                 :            :         MLX5_ASSERT(tbl);
    4546                 :            :         MLX5_ASSERT(tbl_data->jump.action);
    4547                 :          0 :         dev_flow->handle->rix_jump = tbl_data->idx;
    4548                 :          0 :         dev_flow->dv.jump = &tbl_data->jump;
    4549                 :            :         return 0;
    4550                 :            : }
    4551                 :            : 
    4552                 :            : int
    4553                 :          0 : mlx5_flow_dv_port_id_match_cb(void *tool_ctx __rte_unused,
    4554                 :            :                               struct mlx5_list_entry *entry, void *cb_ctx)
    4555                 :            : {
    4556                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4557                 :          0 :         struct mlx5_flow_dv_port_id_action_resource *ref = ctx->data;
    4558                 :            :         struct mlx5_flow_dv_port_id_action_resource *res =
    4559                 :            :                                        container_of(entry, typeof(*res), entry);
    4560                 :            : 
    4561                 :          0 :         return ref->port_id != res->port_id;
    4562                 :            : }
    4563                 :            : 
    4564                 :            : struct mlx5_list_entry *
    4565                 :          0 : mlx5_flow_dv_port_id_create_cb(void *tool_ctx, void *cb_ctx)
    4566                 :            : {
    4567                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4568                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4569                 :          0 :         struct mlx5_flow_dv_port_id_action_resource *ref = ctx->data;
    4570                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4571                 :            :         uint32_t idx;
    4572                 :            :         int ret;
    4573                 :            : 
    4574                 :            :         /* Register new port id action resource. */
    4575                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID], &idx);
    4576         [ #  # ]:          0 :         if (!resource) {
    4577                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4578                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4579                 :            :                                    "cannot allocate port_id action memory");
    4580                 :          0 :                 return NULL;
    4581                 :            :         }
    4582                 :          0 :         *resource = *ref;
    4583                 :          0 :         ret = mlx5_flow_os_create_flow_action_dest_port(sh->fdb_domain,
    4584                 :            :                                                         ref->port_id,
    4585                 :            :                                                         &resource->action);
    4586                 :            :         if (ret) {
    4587                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], idx);
    4588                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4589                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4590                 :            :                                    "cannot create action");
    4591                 :          0 :                 return NULL;
    4592                 :            :         }
    4593                 :          0 :         resource->idx = idx;
    4594                 :          0 :         return &resource->entry;
    4595                 :            : }
    4596                 :            : 
    4597                 :            : struct mlx5_list_entry *
    4598                 :          0 : mlx5_flow_dv_port_id_clone_cb(void *tool_ctx,
    4599                 :            :                               struct mlx5_list_entry *entry __rte_unused,
    4600                 :            :                               void *cb_ctx)
    4601                 :            : {
    4602                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4603                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4604                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4605                 :            :         struct mlx5_flow_dv_port_id_action_resource *old_resource;
    4606                 :            :         uint32_t idx;
    4607                 :            : 
    4608                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID], &idx);
    4609         [ #  # ]:          0 :         if (!resource) {
    4610                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4611                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4612                 :            :                                    "cannot allocate port_id action memory");
    4613                 :          0 :                 return NULL;
    4614                 :            :         }
    4615                 :            :         old_resource = container_of(entry, typeof(*old_resource), entry);
    4616                 :            :         memcpy(resource, old_resource, sizeof(*old_resource));
    4617                 :          0 :         resource->idx = idx;
    4618                 :          0 :         return &resource->entry;
    4619                 :            : }
    4620                 :            : 
    4621                 :            : void
    4622                 :          0 : mlx5_flow_dv_port_id_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4623                 :            : {
    4624                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4625                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource =
    4626                 :            :                                   container_of(entry, typeof(*resource), entry);
    4627                 :            : 
    4628                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], resource->idx);
    4629                 :          0 : }
    4630                 :            : 
    4631                 :            : /**
    4632                 :            :  * Find existing table port ID resource or create and register a new one.
    4633                 :            :  *
    4634                 :            :  * @param[in, out] dev
    4635                 :            :  *   Pointer to rte_eth_dev structure.
    4636                 :            :  * @param[in, out] ref
    4637                 :            :  *   Pointer to port ID action resource reference.
    4638                 :            :  * @parm[in, out] dev_flow
    4639                 :            :  *   Pointer to the dev_flow.
    4640                 :            :  * @param[out] error
    4641                 :            :  *   pointer to error structure.
    4642                 :            :  *
    4643                 :            :  * @return
    4644                 :            :  *   0 on success otherwise -errno and errno is set.
    4645                 :            :  */
    4646                 :            : static int
    4647                 :          0 : flow_dv_port_id_action_resource_register
    4648                 :            :                         (struct rte_eth_dev *dev,
    4649                 :            :                          struct mlx5_flow_dv_port_id_action_resource *ref,
    4650                 :            :                          struct mlx5_flow *dev_flow,
    4651                 :            :                          struct rte_flow_error *error)
    4652                 :            : {
    4653                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4654                 :            :         struct mlx5_list_entry *entry;
    4655                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
    4656                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4657                 :            :                 .error = error,
    4658                 :            :                 .data = ref,
    4659                 :            :         };
    4660                 :            : 
    4661                 :          0 :         entry = mlx5_list_register(priv->sh->port_id_action_list, &ctx);
    4662         [ #  # ]:          0 :         if (!entry)
    4663                 :          0 :                 return -rte_errno;
    4664                 :            :         resource = container_of(entry, typeof(*resource), entry);
    4665                 :          0 :         dev_flow->dv.port_id_action = resource;
    4666                 :          0 :         dev_flow->handle->rix_port_id_action = resource->idx;
    4667                 :          0 :         return 0;
    4668                 :            : }
    4669                 :            : 
    4670                 :            : int
    4671                 :          0 : mlx5_flow_dv_push_vlan_match_cb(void *tool_ctx __rte_unused,
    4672                 :            :                                 struct mlx5_list_entry *entry, void *cb_ctx)
    4673                 :            : {
    4674                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4675                 :          0 :         struct mlx5_flow_dv_push_vlan_action_resource *ref = ctx->data;
    4676                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *res =
    4677                 :            :                                        container_of(entry, typeof(*res), entry);
    4678                 :            : 
    4679                 :          0 :         return ref->vlan_tag != res->vlan_tag || ref->ft_type != res->ft_type;
    4680                 :            : }
    4681                 :            : 
    4682                 :            : struct mlx5_list_entry *
    4683                 :          0 : mlx5_flow_dv_push_vlan_create_cb(void *tool_ctx, void *cb_ctx)
    4684                 :            : {
    4685                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4686                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4687                 :          0 :         struct mlx5_flow_dv_push_vlan_action_resource *ref = ctx->data;
    4688                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4689                 :            :         struct mlx5dv_dr_domain *domain;
    4690                 :            :         uint32_t idx;
    4691                 :            :         int ret;
    4692                 :            : 
    4693                 :            :         /* Register new port id action resource. */
    4694                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PUSH_VLAN], &idx);
    4695         [ #  # ]:          0 :         if (!resource) {
    4696                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4697                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4698                 :            :                                    "cannot allocate push_vlan action memory");
    4699                 :          0 :                 return NULL;
    4700                 :            :         }
    4701                 :          0 :         *resource = *ref;
    4702         [ #  # ]:          0 :         if (ref->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    4703                 :          0 :                 domain = sh->fdb_domain;
    4704         [ #  # ]:          0 :         else if (ref->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
    4705                 :          0 :                 domain = sh->rx_domain;
    4706                 :            :         else
    4707                 :          0 :                 domain = sh->tx_domain;
    4708                 :          0 :         ret = mlx5_flow_os_create_flow_action_push_vlan(domain, ref->vlan_tag,
    4709                 :            :                                                         &resource->action);
    4710                 :            :         if (ret) {
    4711                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx);
    4712                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4713                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4714                 :            :                                    "cannot create push vlan action");
    4715                 :          0 :                 return NULL;
    4716                 :            :         }
    4717                 :          0 :         resource->idx = idx;
    4718                 :          0 :         return &resource->entry;
    4719                 :            : }
    4720                 :            : 
    4721                 :            : struct mlx5_list_entry *
    4722                 :          0 : mlx5_flow_dv_push_vlan_clone_cb(void *tool_ctx,
    4723                 :            :                                 struct mlx5_list_entry *entry __rte_unused,
    4724                 :            :                                 void *cb_ctx)
    4725                 :            : {
    4726                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4727                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    4728                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4729                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *old_resource;
    4730                 :            :         uint32_t idx;
    4731                 :            : 
    4732                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PUSH_VLAN], &idx);
    4733         [ #  # ]:          0 :         if (!resource) {
    4734                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    4735                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4736                 :            :                                    "cannot allocate push_vlan action memory");
    4737                 :          0 :                 return NULL;
    4738                 :            :         }
    4739                 :            :         old_resource = container_of(entry, typeof(*old_resource), entry);
    4740                 :            :         memcpy(resource, old_resource, sizeof(*old_resource));
    4741                 :          0 :         resource->idx = idx;
    4742                 :          0 :         return &resource->entry;
    4743                 :            : }
    4744                 :            : 
    4745                 :            : void
    4746                 :          0 : mlx5_flow_dv_push_vlan_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    4747                 :            : {
    4748                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    4749                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource =
    4750                 :            :                                   container_of(entry, typeof(*resource), entry);
    4751                 :            : 
    4752                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], resource->idx);
    4753                 :          0 : }
    4754                 :            : 
    4755                 :            : /**
    4756                 :            :  * Find existing push vlan resource or create and register a new one.
    4757                 :            :  *
    4758                 :            :  * @param [in, out] dev
    4759                 :            :  *   Pointer to rte_eth_dev structure.
    4760                 :            :  * @param[in, out] ref
    4761                 :            :  *   Pointer to port ID action resource reference.
    4762                 :            :  * @parm[in, out] dev_flow
    4763                 :            :  *   Pointer to the dev_flow.
    4764                 :            :  * @param[out] error
    4765                 :            :  *   pointer to error structure.
    4766                 :            :  *
    4767                 :            :  * @return
    4768                 :            :  *   0 on success otherwise -errno and errno is set.
    4769                 :            :  */
    4770                 :            : static int
    4771                 :          0 : flow_dv_push_vlan_action_resource_register
    4772                 :            :                        (struct rte_eth_dev *dev,
    4773                 :            :                         struct mlx5_flow_dv_push_vlan_action_resource *ref,
    4774                 :            :                         struct mlx5_flow *dev_flow,
    4775                 :            :                         struct rte_flow_error *error)
    4776                 :            : {
    4777                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    4778                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
    4779                 :            :         struct mlx5_list_entry *entry;
    4780                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    4781                 :            :                 .error = error,
    4782                 :            :                 .data = ref,
    4783                 :            :         };
    4784                 :            : 
    4785                 :          0 :         entry = mlx5_list_register(priv->sh->push_vlan_action_list, &ctx);
    4786         [ #  # ]:          0 :         if (!entry)
    4787                 :          0 :                 return -rte_errno;
    4788                 :            :         resource = container_of(entry, typeof(*resource), entry);
    4789                 :            : 
    4790                 :          0 :         dev_flow->handle->dvh.rix_push_vlan = resource->idx;
    4791                 :          0 :         dev_flow->dv.push_vlan_res = resource;
    4792                 :          0 :         return 0;
    4793                 :            : }
    4794                 :            : 
    4795                 :            : /**
    4796                 :            :  * Get the size of specific rte_flow_item_type hdr size
    4797                 :            :  *
    4798                 :            :  * @param[in] item_type
    4799                 :            :  *   Tested rte_flow_item_type.
    4800                 :            :  *
    4801                 :            :  * @return
    4802                 :            :  *   sizeof struct item_type, 0 if void or irrelevant.
    4803                 :            :  */
    4804                 :            : size_t
    4805         [ #  # ]:          0 : mlx5_flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type)
    4806                 :            : {
    4807                 :            :         size_t retval;
    4808                 :            : 
    4809                 :            :         switch (item_type) {
    4810                 :            :         case RTE_FLOW_ITEM_TYPE_ETH:
    4811                 :            :                 retval = sizeof(struct rte_ether_hdr);
    4812                 :            :                 break;
    4813                 :            :         case RTE_FLOW_ITEM_TYPE_VLAN:
    4814                 :            :                 retval = sizeof(struct rte_vlan_hdr);
    4815                 :            :                 break;
    4816                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:
    4817                 :            :                 retval = sizeof(struct rte_ipv4_hdr);
    4818                 :            :                 break;
    4819                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:
    4820                 :            :                 retval = sizeof(struct rte_ipv6_hdr);
    4821                 :            :                 break;
    4822                 :            :         case RTE_FLOW_ITEM_TYPE_UDP:
    4823                 :            :                 retval = sizeof(struct rte_udp_hdr);
    4824                 :            :                 break;
    4825                 :            :         case RTE_FLOW_ITEM_TYPE_TCP:
    4826                 :            :                 retval = sizeof(struct rte_tcp_hdr);
    4827                 :            :                 break;
    4828                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN:
    4829                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    4830                 :            :                 retval = sizeof(struct rte_vxlan_hdr);
    4831                 :            :                 break;
    4832                 :            :         case RTE_FLOW_ITEM_TYPE_GRE:
    4833                 :            :         case RTE_FLOW_ITEM_TYPE_NVGRE:
    4834                 :            :                 retval = sizeof(struct rte_gre_hdr);
    4835                 :            :                 break;
    4836                 :            :         case RTE_FLOW_ITEM_TYPE_MPLS:
    4837                 :            :                 retval = sizeof(struct rte_mpls_hdr);
    4838                 :            :                 break;
    4839                 :            :         case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
    4840                 :            :         default:
    4841                 :            :                 retval = 0;
    4842                 :            :                 break;
    4843                 :            :         }
    4844                 :          0 :         return retval;
    4845                 :            : }
    4846                 :            : 
    4847                 :            : #define MLX5_ENCAP_IPV4_VERSION         0x40
    4848                 :            : #define MLX5_ENCAP_IPV4_IHL_MIN         0x05
    4849                 :            : #define MLX5_ENCAP_IPV4_TTL_DEF         0x40
    4850                 :            : #define MLX5_ENCAP_IPV6_VTC_FLOW        0x60000000
    4851                 :            : #define MLX5_ENCAP_IPV6_HOP_LIMIT       0xff
    4852                 :            : #define MLX5_ENCAP_VXLAN_FLAGS          0x08000000
    4853                 :            : #define MLX5_ENCAP_VXLAN_GPE_FLAGS      0x04
    4854                 :            : 
    4855                 :            : /**
    4856                 :            :  * Convert the encap action data from list of rte_flow_item to raw buffer
    4857                 :            :  *
    4858                 :            :  * @param[in] items
    4859                 :            :  *   Pointer to rte_flow_item objects list.
    4860                 :            :  * @param[out] buf
    4861                 :            :  *   Pointer to the output buffer.
    4862                 :            :  * @param[out] size
    4863                 :            :  *   Pointer to the output buffer size.
    4864                 :            :  * @param[out] error
    4865                 :            :  *   Pointer to the error structure.
    4866                 :            :  *
    4867                 :            :  * @return
    4868                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    4869                 :            :  */
    4870                 :            : int
    4871                 :          0 : mlx5_flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
    4872                 :            :                                 size_t *size, struct rte_flow_error *error)
    4873                 :            : {
    4874                 :            :         struct rte_ether_hdr *eth = NULL;
    4875                 :            :         struct rte_vlan_hdr *vlan = NULL;
    4876                 :            :         struct rte_ipv4_hdr *ipv4 = NULL;
    4877                 :            :         struct rte_ipv6_hdr *ipv6 = NULL;
    4878                 :            :         struct rte_udp_hdr *udp = NULL;
    4879                 :            :         struct rte_vxlan_hdr *vxlan = NULL;
    4880                 :            :         struct rte_vxlan_gpe_hdr *vxlan_gpe = NULL;
    4881                 :            :         struct rte_gre_hdr *gre = NULL;
    4882                 :            :         size_t len;
    4883                 :            :         size_t temp_size = 0;
    4884                 :            : 
    4885         [ #  # ]:          0 :         if (!items)
    4886                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4887                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    4888                 :            :                                           NULL, "invalid empty data");
    4889         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    4890                 :          0 :                 len = mlx5_flow_dv_get_item_hdr_len(items->type);
    4891         [ #  # ]:          0 :                 if (len + temp_size > MLX5_ENCAP_MAX_LEN)
    4892                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4893                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    4894                 :          0 :                                                   (void *)items->type,
    4895                 :            :                                                   "items total size is too big"
    4896                 :            :                                                   " for encap action");
    4897         [ #  # ]:          0 :                 if (items->spec)
    4898         [ #  # ]:          0 :                         rte_memcpy(&buf[temp_size], items->spec, len);
    4899   [ #  #  #  #  :          0 :                 switch (items->type) {
          #  #  #  #  #  
                      # ]
    4900                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    4901                 :          0 :                         eth = (struct rte_ether_hdr *)&buf[temp_size];
    4902                 :          0 :                         break;
    4903                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    4904                 :          0 :                         vlan = (struct rte_vlan_hdr *)&buf[temp_size];
    4905         [ #  # ]:          0 :                         if (!eth)
    4906                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4907                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4908                 :            :                                                 (void *)items->type,
    4909                 :            :                                                 "eth header not found");
    4910         [ #  # ]:          0 :                         if (!eth->ether_type)
    4911                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_VLAN);
    4912                 :            :                         break;
    4913                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    4914                 :          0 :                         ipv4 = (struct rte_ipv4_hdr *)&buf[temp_size];
    4915         [ #  # ]:          0 :                         if (!vlan && !eth)
    4916                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4917                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4918                 :            :                                                 (void *)items->type,
    4919                 :            :                                                 "neither eth nor vlan"
    4920                 :            :                                                 " header found");
    4921   [ #  #  #  # ]:          0 :                         if (vlan && !vlan->eth_proto)
    4922                 :          0 :                                 vlan->eth_proto = RTE_BE16(RTE_ETHER_TYPE_IPV4);
    4923   [ #  #  #  # ]:          0 :                         else if (eth && !eth->ether_type)
    4924                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV4);
    4925         [ #  # ]:          0 :                         if (!ipv4->version_ihl)
    4926                 :          0 :                                 ipv4->version_ihl = MLX5_ENCAP_IPV4_VERSION |
    4927                 :            :                                                     MLX5_ENCAP_IPV4_IHL_MIN;
    4928         [ #  # ]:          0 :                         if (!ipv4->time_to_live)
    4929                 :          0 :                                 ipv4->time_to_live = MLX5_ENCAP_IPV4_TTL_DEF;
    4930                 :            :                         break;
    4931                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    4932                 :          0 :                         ipv6 = (struct rte_ipv6_hdr *)&buf[temp_size];
    4933         [ #  # ]:          0 :                         if (!vlan && !eth)
    4934                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4935                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4936                 :            :                                                 (void *)items->type,
    4937                 :            :                                                 "neither eth nor vlan"
    4938                 :            :                                                 " header found");
    4939   [ #  #  #  # ]:          0 :                         if (vlan && !vlan->eth_proto)
    4940                 :          0 :                                 vlan->eth_proto = RTE_BE16(RTE_ETHER_TYPE_IPV6);
    4941   [ #  #  #  # ]:          0 :                         else if (eth && !eth->ether_type)
    4942                 :          0 :                                 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
    4943         [ #  # ]:          0 :                         if (!ipv6->vtc_flow)
    4944                 :          0 :                                 ipv6->vtc_flow =
    4945                 :            :                                         RTE_BE32(MLX5_ENCAP_IPV6_VTC_FLOW);
    4946         [ #  # ]:          0 :                         if (!ipv6->hop_limits)
    4947                 :          0 :                                 ipv6->hop_limits = MLX5_ENCAP_IPV6_HOP_LIMIT;
    4948                 :            :                         break;
    4949                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    4950                 :          0 :                         udp = (struct rte_udp_hdr *)&buf[temp_size];
    4951         [ #  # ]:          0 :                         if (!ipv4 && !ipv6)
    4952                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4953                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4954                 :            :                                                 (void *)items->type,
    4955                 :            :                                                 "ip header not found");
    4956   [ #  #  #  # ]:          0 :                         if (ipv4 && !ipv4->next_proto_id)
    4957                 :          0 :                                 ipv4->next_proto_id = IPPROTO_UDP;
    4958   [ #  #  #  # ]:          0 :                         else if (ipv6 && !ipv6->proto)
    4959                 :          0 :                                 ipv6->proto = IPPROTO_UDP;
    4960                 :            :                         break;
    4961                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    4962                 :          0 :                         vxlan = (struct rte_vxlan_hdr *)&buf[temp_size];
    4963         [ #  # ]:          0 :                         if (!udp)
    4964                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4965                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4966                 :            :                                                 (void *)items->type,
    4967                 :            :                                                 "udp header not found");
    4968         [ #  # ]:          0 :                         if (!udp->dst_port)
    4969                 :          0 :                                 udp->dst_port = RTE_BE16(MLX5_UDP_PORT_VXLAN);
    4970         [ #  # ]:          0 :                         if (!vxlan->vx_flags)
    4971                 :          0 :                                 vxlan->vx_flags =
    4972                 :            :                                         RTE_BE32(MLX5_ENCAP_VXLAN_FLAGS);
    4973                 :            :                         break;
    4974                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    4975                 :          0 :                         vxlan_gpe = (struct rte_vxlan_gpe_hdr *)&buf[temp_size];
    4976         [ #  # ]:          0 :                         if (!udp)
    4977                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4978                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4979                 :            :                                                 (void *)items->type,
    4980                 :            :                                                 "udp header not found");
    4981         [ #  # ]:          0 :                         if (!vxlan_gpe->proto)
    4982                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4983                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4984                 :            :                                                 (void *)items->type,
    4985                 :            :                                                 "next protocol not found");
    4986         [ #  # ]:          0 :                         if (!udp->dst_port)
    4987                 :          0 :                                 udp->dst_port =
    4988                 :            :                                         RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
    4989         [ #  # ]:          0 :                         if (!vxlan_gpe->vx_flags)
    4990                 :          0 :                                 vxlan_gpe->vx_flags =
    4991                 :            :                                                 MLX5_ENCAP_VXLAN_GPE_FLAGS;
    4992                 :            :                         break;
    4993                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
    4994                 :            :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    4995                 :          0 :                         gre = (struct rte_gre_hdr *)&buf[temp_size];
    4996         [ #  # ]:          0 :                         if (!gre->proto)
    4997                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4998                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    4999                 :          0 :                                                 (void *)items->type,
    5000                 :            :                                                 "next protocol not found");
    5001         [ #  # ]:          0 :                         if (!ipv4 && !ipv6)
    5002                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    5003                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    5004                 :          0 :                                                 (void *)items->type,
    5005                 :            :                                                 "ip header not found");
    5006   [ #  #  #  # ]:          0 :                         if (ipv4 && !ipv4->next_proto_id)
    5007                 :          0 :                                 ipv4->next_proto_id = IPPROTO_GRE;
    5008   [ #  #  #  # ]:          0 :                         else if (ipv6 && !ipv6->proto)
    5009                 :          0 :                                 ipv6->proto = IPPROTO_GRE;
    5010                 :            :                         break;
    5011                 :            :                 case RTE_FLOW_ITEM_TYPE_VOID:
    5012                 :            :                         break;
    5013                 :          0 :                 default:
    5014                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5015                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5016                 :          0 :                                                   (void *)items->type,
    5017                 :            :                                                   "unsupported item type");
    5018                 :            :                         break;
    5019                 :            :                 }
    5020                 :            :                 temp_size += len;
    5021                 :            :         }
    5022                 :          0 :         *size = temp_size;
    5023                 :          0 :         return 0;
    5024                 :            : }
    5025                 :            : 
    5026                 :            : static int
    5027                 :          0 : flow_dv_zero_encap_udp_csum(void *data, struct rte_flow_error *error)
    5028                 :            : {
    5029                 :            :         struct rte_ether_hdr *eth = NULL;
    5030                 :            :         struct rte_vlan_hdr *vlan = NULL;
    5031                 :            :         struct rte_ipv4_hdr *ipv4 = NULL;
    5032                 :            :         struct rte_ipv6_hdr *ipv6 = NULL;
    5033                 :            :         struct rte_udp_hdr *udp = NULL;
    5034                 :            :         char *next_hdr;
    5035                 :            :         uint16_t proto;
    5036                 :            : 
    5037                 :            :         eth = (struct rte_ether_hdr *)data;
    5038                 :          0 :         next_hdr = (char *)(eth + 1);
    5039                 :          0 :         proto = RTE_BE16(eth->ether_type);
    5040                 :            : 
    5041                 :            :         /* VLAN skipping */
    5042         [ #  # ]:          0 :         while (proto == RTE_ETHER_TYPE_VLAN || proto == RTE_ETHER_TYPE_QINQ) {
    5043                 :            :                 vlan = (struct rte_vlan_hdr *)next_hdr;
    5044                 :          0 :                 proto = RTE_BE16(vlan->eth_proto);
    5045                 :          0 :                 next_hdr += sizeof(struct rte_vlan_hdr);
    5046                 :            :         }
    5047                 :            : 
    5048                 :            :         /* non IPv4/IPv6 header. not supported */
    5049         [ #  # ]:          0 :         if (proto != RTE_ETHER_TYPE_IPV4 && proto != RTE_ETHER_TYPE_IPV6) {
    5050                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5051                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5052                 :            :                                           NULL, "Cannot offload non IPv4/IPv6");
    5053                 :            :         }
    5054                 :            : 
    5055         [ #  # ]:          0 :         if (proto == RTE_ETHER_TYPE_IPV4) {
    5056                 :            :                 ipv4 = (struct rte_ipv4_hdr *)next_hdr;
    5057                 :            :                 /* ignore non UDP */
    5058         [ #  # ]:          0 :                 if (ipv4->next_proto_id != IPPROTO_UDP)
    5059                 :            :                         return 0;
    5060                 :          0 :                 udp = (struct rte_udp_hdr *)(ipv4 + 1);
    5061                 :            :         } else {
    5062                 :            :                 ipv6 = (struct rte_ipv6_hdr *)next_hdr;
    5063                 :            :                 /* ignore non UDP */
    5064         [ #  # ]:          0 :                 if (ipv6->proto != IPPROTO_UDP)
    5065                 :            :                         return 0;
    5066                 :          0 :                 udp = (struct rte_udp_hdr *)(ipv6 + 1);
    5067                 :            :         }
    5068                 :            : 
    5069                 :          0 :         udp->dgram_cksum = 0;
    5070                 :            : 
    5071                 :          0 :         return 0;
    5072                 :            : }
    5073                 :            : 
    5074                 :            : /**
    5075                 :            :  * Convert L2 encap action to DV specification.
    5076                 :            :  *
    5077                 :            :  * @param[in] dev
    5078                 :            :  *   Pointer to rte_eth_dev structure.
    5079                 :            :  * @param[in] action
    5080                 :            :  *   Pointer to action structure.
    5081                 :            :  * @param[in, out] dev_flow
    5082                 :            :  *   Pointer to the mlx5_flow.
    5083                 :            :  * @param[in] transfer
    5084                 :            :  *   Mark if the flow is E-Switch flow.
    5085                 :            :  * @param[out] error
    5086                 :            :  *   Pointer to the error structure.
    5087                 :            :  *
    5088                 :            :  * @return
    5089                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5090                 :            :  */
    5091                 :            : static int
    5092                 :          0 : flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
    5093                 :            :                                const struct rte_flow_action *action,
    5094                 :            :                                struct mlx5_flow *dev_flow,
    5095                 :            :                                uint8_t transfer,
    5096                 :            :                                struct rte_flow_error *error)
    5097                 :            : {
    5098                 :            :         const struct rte_flow_item *encap_data;
    5099                 :            :         const struct rte_flow_action_raw_encap *raw_encap_data;
    5100         [ #  # ]:          0 :         struct mlx5_flow_dv_encap_decap_resource res = {
    5101                 :            :                 .reformat_type =
    5102                 :            :                         MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
    5103                 :            :                 .ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
    5104                 :            :                                       MLX5DV_FLOW_TABLE_TYPE_NIC_TX,
    5105                 :            :         };
    5106                 :            : 
    5107         [ #  # ]:          0 :         if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    5108                 :          0 :                 raw_encap_data =
    5109                 :            :                         (const struct rte_flow_action_raw_encap *)action->conf;
    5110                 :          0 :                 res.size = raw_encap_data->size;
    5111                 :          0 :                 memcpy(res.buf, raw_encap_data->data, res.size);
    5112                 :            :         } else {
    5113         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
    5114                 :          0 :                         encap_data =
    5115                 :            :                                 ((const struct rte_flow_action_vxlan_encap *)
    5116                 :          0 :                                                 action->conf)->definition;
    5117                 :            :                 else
    5118                 :          0 :                         encap_data =
    5119                 :            :                                 ((const struct rte_flow_action_nvgre_encap *)
    5120                 :          0 :                                                 action->conf)->definition;
    5121         [ #  # ]:          0 :                 if (mlx5_flow_dv_convert_encap_data(encap_data, res.buf,
    5122                 :            :                                                     &res.size, error))
    5123                 :          0 :                         return -rte_errno;
    5124                 :            :         }
    5125         [ #  # ]:          0 :         if (flow_dv_zero_encap_udp_csum(res.buf, error))
    5126                 :          0 :                 return -rte_errno;
    5127         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5128                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5129                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5130                 :            :                                           NULL, "can't create L2 encap action");
    5131                 :            :         return 0;
    5132                 :            : }
    5133                 :            : 
    5134                 :            : /**
    5135                 :            :  * Convert L2 decap action to DV specification.
    5136                 :            :  *
    5137                 :            :  * @param[in] dev
    5138                 :            :  *   Pointer to rte_eth_dev structure.
    5139                 :            :  * @param[in, out] dev_flow
    5140                 :            :  *   Pointer to the mlx5_flow.
    5141                 :            :  * @param[in] transfer
    5142                 :            :  *   Mark if the flow is E-Switch flow.
    5143                 :            :  * @param[out] error
    5144                 :            :  *   Pointer to the error structure.
    5145                 :            :  *
    5146                 :            :  * @return
    5147                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5148                 :            :  */
    5149                 :            : static int
    5150                 :          0 : flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
    5151                 :            :                                struct mlx5_flow *dev_flow,
    5152                 :            :                                uint8_t transfer,
    5153                 :            :                                struct rte_flow_error *error)
    5154                 :            : {
    5155         [ #  # ]:          0 :         struct mlx5_flow_dv_encap_decap_resource res = {
    5156                 :            :                 .size = 0,
    5157                 :            :                 .reformat_type =
    5158                 :            :                         MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
    5159                 :            :                 .ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
    5160                 :            :                                       MLX5DV_FLOW_TABLE_TYPE_NIC_RX,
    5161                 :            :         };
    5162                 :            : 
    5163         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5164                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5165                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5166                 :            :                                           NULL, "can't create L2 decap action");
    5167                 :            :         return 0;
    5168                 :            : }
    5169                 :            : 
    5170                 :            : /**
    5171                 :            :  * Convert raw decap/encap (L3 tunnel) action to DV specification.
    5172                 :            :  *
    5173                 :            :  * @param[in] dev
    5174                 :            :  *   Pointer to rte_eth_dev structure.
    5175                 :            :  * @param[in] action
    5176                 :            :  *   Pointer to action structure.
    5177                 :            :  * @param[in, out] dev_flow
    5178                 :            :  *   Pointer to the mlx5_flow.
    5179                 :            :  * @param[in] attr
    5180                 :            :  *   Pointer to the flow attributes.
    5181                 :            :  * @param[out] error
    5182                 :            :  *   Pointer to the error structure.
    5183                 :            :  *
    5184                 :            :  * @return
    5185                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5186                 :            :  */
    5187                 :            : static int
    5188         [ #  # ]:          0 : flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
    5189                 :            :                                 const struct rte_flow_action *action,
    5190                 :            :                                 struct mlx5_flow *dev_flow,
    5191                 :            :                                 const struct rte_flow_attr *attr,
    5192                 :            :                                 struct rte_flow_error *error)
    5193                 :            : {
    5194                 :            :         const struct rte_flow_action_raw_encap *encap_data;
    5195                 :            :         struct mlx5_flow_dv_encap_decap_resource res;
    5196                 :            : 
    5197                 :            :         memset(&res, 0, sizeof(res));
    5198                 :          0 :         encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
    5199                 :          0 :         res.size = encap_data->size;
    5200         [ #  # ]:          0 :         memcpy(res.buf, encap_data->data, res.size);
    5201         [ #  # ]:          0 :         res.reformat_type = res.size < MLX5_ENCAPSULATION_DECISION_SIZE ?
    5202                 :            :                 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 :
    5203                 :            :                 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
    5204         [ #  # ]:          0 :         if (attr->transfer)
    5205                 :          0 :                 res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
    5206                 :            :         else
    5207                 :          0 :                 res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
    5208                 :            :                                              MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
    5209         [ #  # ]:          0 :         if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
    5210                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5211                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    5212                 :            :                                           NULL, "can't create encap action");
    5213                 :            :         return 0;
    5214                 :            : }
    5215                 :            : 
    5216                 :            : /**
    5217                 :            :  * Create action push VLAN.
    5218                 :            :  *
    5219                 :            :  * @param[in] dev
    5220                 :            :  *   Pointer to rte_eth_dev structure.
    5221                 :            :  * @param[in] attr
    5222                 :            :  *   Pointer to the flow attributes.
    5223                 :            :  * @param[in] vlan
    5224                 :            :  *   Pointer to the vlan to push to the Ethernet header.
    5225                 :            :  * @param[in, out] dev_flow
    5226                 :            :  *   Pointer to the mlx5_flow.
    5227                 :            :  * @param[out] error
    5228                 :            :  *   Pointer to the error structure.
    5229                 :            :  *
    5230                 :            :  * @return
    5231                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5232                 :            :  */
    5233                 :            : static int
    5234         [ #  # ]:          0 : flow_dv_create_action_push_vlan(struct rte_eth_dev *dev,
    5235                 :            :                                 const struct rte_flow_attr *attr,
    5236                 :            :                                 const struct rte_vlan_hdr *vlan,
    5237                 :            :                                 struct mlx5_flow *dev_flow,
    5238                 :            :                                 struct rte_flow_error *error)
    5239                 :            : {
    5240                 :            :         struct mlx5_flow_dv_push_vlan_action_resource res;
    5241                 :            : 
    5242                 :            :         memset(&res, 0, sizeof(res));
    5243                 :          0 :         res.vlan_tag =
    5244         [ #  # ]:          0 :                 rte_cpu_to_be_32(((uint32_t)vlan->eth_proto) << 16 |
    5245                 :            :                                  vlan->vlan_tci);
    5246         [ #  # ]:          0 :         if (attr->transfer)
    5247                 :          0 :                 res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
    5248                 :            :         else
    5249                 :          0 :                 res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
    5250                 :            :                                              MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
    5251                 :          0 :         return flow_dv_push_vlan_action_resource_register
    5252                 :            :                                             (dev, &res, dev_flow, error);
    5253                 :            : }
    5254                 :            : 
    5255                 :            : /**
    5256                 :            :  * Validate the modify-header actions.
    5257                 :            :  *
    5258                 :            :  * @param[in] action_flags
    5259                 :            :  *   Holds the actions detected until now.
    5260                 :            :  * @param[in] action
    5261                 :            :  *   Pointer to the modify action.
    5262                 :            :  * @param[out] error
    5263                 :            :  *   Pointer to error structure.
    5264                 :            :  *
    5265                 :            :  * @return
    5266                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5267                 :            :  */
    5268                 :            : static int
    5269                 :          0 : flow_dv_validate_action_modify_hdr(const uint64_t action_flags,
    5270                 :            :                                    const struct rte_flow_action *action,
    5271                 :            :                                    struct rte_flow_error *error)
    5272                 :            : {
    5273   [ #  #  #  # ]:          0 :         if (action->type != RTE_FLOW_ACTION_TYPE_DEC_TTL && !action->conf)
    5274                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5275                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5276                 :            :                                           NULL, "action configuration not set");
    5277                 :            : 
    5278         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    5279                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5280                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5281                 :            :                                           "can't have encap action before"
    5282                 :            :                                           " modify action");
    5283                 :            :         return 0;
    5284                 :            : }
    5285                 :            : 
    5286                 :            : /**
    5287                 :            :  * Validate the modify-header MAC address actions.
    5288                 :            :  *
    5289                 :            :  * @param[in] action_flags
    5290                 :            :  *   Holds the actions detected until now.
    5291                 :            :  * @param[in] action
    5292                 :            :  *   Pointer to the modify action.
    5293                 :            :  * @param[in] item_flags
    5294                 :            :  *   Holds the items detected.
    5295                 :            :  * @param[out] error
    5296                 :            :  *   Pointer to error structure.
    5297                 :            :  *
    5298                 :            :  * @return
    5299                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5300                 :            :  */
    5301                 :            : static int
    5302                 :          0 : flow_dv_validate_action_modify_mac(const uint64_t action_flags,
    5303                 :            :                                    const struct rte_flow_action *action,
    5304                 :            :                                    const uint64_t item_flags,
    5305                 :            :                                    struct rte_flow_error *error)
    5306                 :            : {
    5307                 :            :         int ret = 0;
    5308                 :            : 
    5309                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5310         [ #  # ]:          0 :         if (!ret) {
    5311         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L2))
    5312                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5313                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5314                 :            :                                                   NULL,
    5315                 :            :                                                   "no L2 item in pattern");
    5316                 :            :         }
    5317                 :            :         return ret;
    5318                 :            : }
    5319                 :            : 
    5320                 :            : /**
    5321                 :            :  * Validate the modify-header IPv4 address actions.
    5322                 :            :  *
    5323                 :            :  * @param[in] action_flags
    5324                 :            :  *   Holds the actions detected until now.
    5325                 :            :  * @param[in] action
    5326                 :            :  *   Pointer to the modify action.
    5327                 :            :  * @param[in] item_flags
    5328                 :            :  *   Holds the items detected.
    5329                 :            :  * @param[out] error
    5330                 :            :  *   Pointer to error structure.
    5331                 :            :  *
    5332                 :            :  * @return
    5333                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5334                 :            :  */
    5335                 :            : static int
    5336                 :          0 : flow_dv_validate_action_modify_ipv4(const uint64_t action_flags,
    5337                 :            :                                     const struct rte_flow_action *action,
    5338                 :            :                                     const uint64_t item_flags,
    5339                 :            :                                     struct rte_flow_error *error)
    5340                 :            : {
    5341                 :            :         int ret = 0;
    5342                 :            :         uint64_t layer;
    5343                 :            : 
    5344                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5345         [ #  # ]:          0 :         if (!ret) {
    5346                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5347         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    5348                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    5349         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5350                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5351                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5352                 :            :                                                   NULL,
    5353                 :            :                                                   "no ipv4 item in pattern");
    5354                 :            :         }
    5355                 :            :         return ret;
    5356                 :            : }
    5357                 :            : 
    5358                 :            : /**
    5359                 :            :  * Validate the modify-header IPv6 address actions.
    5360                 :            :  *
    5361                 :            :  * @param[in] action_flags
    5362                 :            :  *   Holds the actions detected until now.
    5363                 :            :  * @param[in] action
    5364                 :            :  *   Pointer to the modify action.
    5365                 :            :  * @param[in] item_flags
    5366                 :            :  *   Holds the items detected.
    5367                 :            :  * @param[out] error
    5368                 :            :  *   Pointer to error structure.
    5369                 :            :  *
    5370                 :            :  * @return
    5371                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5372                 :            :  */
    5373                 :            : static int
    5374                 :          0 : flow_dv_validate_action_modify_ipv6(const uint64_t action_flags,
    5375                 :            :                                     const struct rte_flow_action *action,
    5376                 :            :                                     const uint64_t item_flags,
    5377                 :            :                                     struct rte_flow_error *error)
    5378                 :            : {
    5379                 :            :         int ret = 0;
    5380                 :            :         uint64_t layer;
    5381                 :            : 
    5382                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5383         [ #  # ]:          0 :         if (!ret) {
    5384                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5385         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    5386                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    5387         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5388                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5389                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5390                 :            :                                                   NULL,
    5391                 :            :                                                   "no ipv6 item in pattern");
    5392                 :            :         }
    5393                 :            :         return ret;
    5394                 :            : }
    5395                 :            : 
    5396                 :            : /**
    5397                 :            :  * Validate the modify-header TP actions.
    5398                 :            :  *
    5399                 :            :  * @param[in] action_flags
    5400                 :            :  *   Holds the actions detected until now.
    5401                 :            :  * @param[in] action
    5402                 :            :  *   Pointer to the modify action.
    5403                 :            :  * @param[in] item_flags
    5404                 :            :  *   Holds the items detected.
    5405                 :            :  * @param[out] error
    5406                 :            :  *   Pointer to error structure.
    5407                 :            :  *
    5408                 :            :  * @return
    5409                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5410                 :            :  */
    5411                 :            : static int
    5412                 :          0 : flow_dv_validate_action_modify_tp(const uint64_t action_flags,
    5413                 :            :                                   const struct rte_flow_action *action,
    5414                 :            :                                   const uint64_t item_flags,
    5415                 :            :                                   struct rte_flow_error *error)
    5416                 :            : {
    5417                 :            :         int ret = 0;
    5418                 :            :         uint64_t layer;
    5419                 :            : 
    5420                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5421         [ #  # ]:          0 :         if (!ret) {
    5422                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5423         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4 :
    5424                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4;
    5425         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5426                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5427                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5428                 :            :                                                   NULL, "no transport layer "
    5429                 :            :                                                   "in pattern");
    5430                 :            :         }
    5431                 :            :         return ret;
    5432                 :            : }
    5433                 :            : 
    5434                 :            : /**
    5435                 :            :  * Validate the modify-header actions of increment/decrement
    5436                 :            :  * TCP Sequence-number.
    5437                 :            :  *
    5438                 :            :  * @param[in] action_flags
    5439                 :            :  *   Holds the actions detected until now.
    5440                 :            :  * @param[in] action
    5441                 :            :  *   Pointer to the modify action.
    5442                 :            :  * @param[in] item_flags
    5443                 :            :  *   Holds the items detected.
    5444                 :            :  * @param[out] error
    5445                 :            :  *   Pointer to error structure.
    5446                 :            :  *
    5447                 :            :  * @return
    5448                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5449                 :            :  */
    5450                 :            : static int
    5451                 :          0 : flow_dv_validate_action_modify_tcp_seq(const uint64_t action_flags,
    5452                 :            :                                        const struct rte_flow_action *action,
    5453                 :            :                                        const uint64_t item_flags,
    5454                 :            :                                        struct rte_flow_error *error)
    5455                 :            : {
    5456                 :            :         int ret = 0;
    5457                 :            :         uint64_t layer;
    5458                 :            : 
    5459                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5460         [ #  # ]:          0 :         if (!ret) {
    5461                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5462         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4_TCP :
    5463                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4_TCP;
    5464         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5465                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5466                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5467                 :            :                                                   NULL, "no TCP item in"
    5468                 :            :                                                   " pattern");
    5469         [ #  # ]:          0 :                 if ((action->type == RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ &&
    5470   [ #  #  #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_DEC_TCP_SEQ)) ||
    5471                 :          0 :                     (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ &&
    5472         [ #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_INC_TCP_SEQ)))
    5473                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5474                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5475                 :            :                                                   NULL,
    5476                 :            :                                                   "cannot decrease and increase"
    5477                 :            :                                                   " TCP sequence number"
    5478                 :            :                                                   " at the same time");
    5479                 :            :         }
    5480                 :            :         return ret;
    5481                 :            : }
    5482                 :            : 
    5483                 :            : /**
    5484                 :            :  * Validate the modify-header actions of increment/decrement
    5485                 :            :  * TCP Acknowledgment number.
    5486                 :            :  *
    5487                 :            :  * @param[in] action_flags
    5488                 :            :  *   Holds the actions detected until now.
    5489                 :            :  * @param[in] action
    5490                 :            :  *   Pointer to the modify action.
    5491                 :            :  * @param[in] item_flags
    5492                 :            :  *   Holds the items detected.
    5493                 :            :  * @param[out] error
    5494                 :            :  *   Pointer to error structure.
    5495                 :            :  *
    5496                 :            :  * @return
    5497                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5498                 :            :  */
    5499                 :            : static int
    5500                 :          0 : flow_dv_validate_action_modify_tcp_ack(const uint64_t action_flags,
    5501                 :            :                                        const struct rte_flow_action *action,
    5502                 :            :                                        const uint64_t item_flags,
    5503                 :            :                                        struct rte_flow_error *error)
    5504                 :            : {
    5505                 :            :         int ret = 0;
    5506                 :            :         uint64_t layer;
    5507                 :            : 
    5508                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5509         [ #  # ]:          0 :         if (!ret) {
    5510                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5511         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L4_TCP :
    5512                 :            :                                  MLX5_FLOW_LAYER_OUTER_L4_TCP;
    5513         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5514                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5515                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5516                 :            :                                                   NULL, "no TCP item in"
    5517                 :            :                                                   " pattern");
    5518         [ #  # ]:          0 :                 if ((action->type == RTE_FLOW_ACTION_TYPE_INC_TCP_ACK &&
    5519   [ #  #  #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_DEC_TCP_ACK)) ||
    5520                 :          0 :                     (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK &&
    5521         [ #  # ]:          0 :                         (action_flags & MLX5_FLOW_ACTION_INC_TCP_ACK)))
    5522                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5523                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5524                 :            :                                                   NULL,
    5525                 :            :                                                   "cannot decrease and increase"
    5526                 :            :                                                   " TCP acknowledgment number"
    5527                 :            :                                                   " at the same time");
    5528                 :            :         }
    5529                 :            :         return ret;
    5530                 :            : }
    5531                 :            : 
    5532                 :            : /**
    5533                 :            :  * Validate the modify-header TTL actions.
    5534                 :            :  *
    5535                 :            :  * @param[in] action_flags
    5536                 :            :  *   Holds the actions detected until now.
    5537                 :            :  * @param[in] action
    5538                 :            :  *   Pointer to the modify action.
    5539                 :            :  * @param[in] item_flags
    5540                 :            :  *   Holds the items detected.
    5541                 :            :  * @param[out] error
    5542                 :            :  *   Pointer to error structure.
    5543                 :            :  *
    5544                 :            :  * @return
    5545                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5546                 :            :  */
    5547                 :            : static int
    5548                 :          0 : flow_dv_validate_action_modify_ttl(const uint64_t action_flags,
    5549                 :            :                                    const struct rte_flow_action *action,
    5550                 :            :                                    const uint64_t item_flags,
    5551                 :            :                                    struct rte_flow_error *error)
    5552                 :            : {
    5553                 :            :         int ret = 0;
    5554                 :            :         uint64_t layer;
    5555                 :            : 
    5556                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5557         [ #  # ]:          0 :         if (!ret) {
    5558                 :          0 :                 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
    5559         [ #  # ]:          0 :                                  MLX5_FLOW_LAYER_INNER_L3 :
    5560                 :            :                                  MLX5_FLOW_LAYER_OUTER_L3;
    5561         [ #  # ]:          0 :                 if (!(item_flags & layer))
    5562                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5563                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    5564                 :            :                                                   NULL,
    5565                 :            :                                                   "no IP protocol in pattern");
    5566                 :            :         }
    5567                 :            :         return ret;
    5568                 :            : }
    5569                 :            : 
    5570                 :            : /**
    5571                 :            :  * Validate the generic modify field actions.
    5572                 :            :  * @param[in] dev
    5573                 :            :  *   Pointer to the rte_eth_dev structure.
    5574                 :            :  * @param[in] action_flags
    5575                 :            :  *   Holds the actions detected until now.
    5576                 :            :  * @param[in] action
    5577                 :            :  *   Pointer to the modify action.
    5578                 :            :  * @param[in] attr
    5579                 :            :  *   Pointer to the flow attributes.
    5580                 :            :  * @param root
    5581                 :            :  *   Whether action is on root table.
    5582                 :            :  * @param[out] error
    5583                 :            :  *   Pointer to error structure.
    5584                 :            :  *
    5585                 :            :  * @return
    5586                 :            :  *   Number of header fields to modify (0 or more) on success,
    5587                 :            :  *   a negative errno value otherwise and rte_errno is set.
    5588                 :            :  */
    5589                 :            : static int
    5590                 :          0 : flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
    5591                 :            :                                    const uint64_t action_flags,
    5592                 :            :                                    const struct rte_flow_action *action,
    5593                 :            :                                    const struct rte_flow_attr *attr,
    5594                 :            :                                    bool root,
    5595                 :            :                                    struct rte_flow_error *error)
    5596                 :            : {
    5597                 :            :         int ret = 0;
    5598                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5599                 :          0 :         struct mlx5_sh_config *config = &priv->sh->config;
    5600                 :          0 :         struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
    5601                 :          0 :         const struct rte_flow_action_modify_field *conf = action->conf;
    5602                 :          0 :         const struct rte_flow_field_data *src_data = &conf->src;
    5603                 :          0 :         const struct rte_flow_field_data *dst_data = &conf->dst;
    5604                 :          0 :         uint32_t dst_width, src_width, width = conf->width;
    5605                 :            : 
    5606                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    5607         [ #  # ]:          0 :         if (ret)
    5608                 :            :                 return ret;
    5609         [ #  # ]:          0 :         if (src_data->field == RTE_FLOW_FIELD_FLEX_ITEM ||
    5610         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_FLEX_ITEM)
    5611                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5612                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5613                 :            :                                 "flex item fields modification"
    5614                 :            :                                 " is not supported");
    5615                 :          0 :         dst_width = mlx5_flow_item_field_width(dev, dst_data->field,
    5616                 :            :                                                -1, attr, error);
    5617                 :          0 :         src_width = mlx5_flow_item_field_width(dev, src_data->field,
    5618                 :            :                                                dst_width, attr, error);
    5619         [ #  # ]:          0 :         if (width == 0)
    5620                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5621                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5622                 :            :                                 "no bits are requested to be modified");
    5623         [ #  # ]:          0 :         else if (width > dst_width || width > src_width)
    5624                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5625                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5626                 :            :                                 "cannot modify more bits than"
    5627                 :            :                                 " the width of a field");
    5628         [ #  # ]:          0 :         if (dst_data->field != RTE_FLOW_FIELD_VALUE &&
    5629                 :            :             dst_data->field != RTE_FLOW_FIELD_POINTER) {
    5630         [ #  # ]:          0 :                 if (dst_data->offset + width > dst_width)
    5631                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5632                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5633                 :            :                                         "destination offset is too big");
    5634                 :          0 :                 ret = mlx5_flow_validate_modify_field_level(dst_data, error);
    5635         [ #  # ]:          0 :                 if (ret)
    5636                 :            :                         return ret;
    5637         [ #  # ]:          0 :                 if (dst_data->tag_index &&
    5638         [ #  # ]:          0 :                     !flow_modify_field_support_tag_array(dst_data->field))
    5639                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5640                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5641                 :            :                                         "destination tag index is not supported");
    5642         [ #  # ]:          0 :                 if (dst_data->class_id)
    5643                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5644                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5645                 :            :                                         "destination class ID is not supported");
    5646                 :            :         }
    5647         [ #  # ]:          0 :         if (src_data->field != RTE_FLOW_FIELD_VALUE &&
    5648                 :            :             src_data->field != RTE_FLOW_FIELD_POINTER) {
    5649         [ #  # ]:          0 :                 if (conf->operation != RTE_FLOW_MODIFY_SET)
    5650                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5651                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5652                 :          0 :                                                   &conf->operation,
    5653                 :            :                                                   "modify field action type add is not"
    5654                 :            :                                                   " supported when src field type is"
    5655                 :            :                                                   " not value/pointer");
    5656         [ #  # ]:          0 :                 if (root)
    5657                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5658                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5659                 :            :                                         "modify field action is not"
    5660                 :            :                                         " supported for group 0");
    5661         [ #  # ]:          0 :                 if (src_data->offset + width > src_width)
    5662                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5663                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5664                 :            :                                         "source offset is too big");
    5665                 :          0 :                 ret = mlx5_flow_validate_modify_field_level(src_data, error);
    5666         [ #  # ]:          0 :                 if (ret)
    5667                 :            :                         return ret;
    5668         [ #  # ]:          0 :                 if (src_data->tag_index &&
    5669         [ #  # ]:          0 :                     !flow_modify_field_support_tag_array(src_data->field))
    5670                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5671                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5672                 :            :                                         "source tag index is not supported");
    5673         [ #  # ]:          0 :                 if (src_data->class_id)
    5674                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    5675                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5676                 :            :                                         "source class ID is not supported");
    5677                 :            :         }
    5678         [ #  # ]:          0 :         if ((dst_data->field == src_data->field) &&
    5679         [ #  # ]:          0 :             (dst_data->level == src_data->level))
    5680                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5681                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5682                 :            :                                 "source and destination fields"
    5683                 :            :                                 " cannot be the same");
    5684                 :          0 :         if (dst_data->field == RTE_FLOW_FIELD_VALUE ||
    5685         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_POINTER ||
    5686                 :            :             dst_data->field == RTE_FLOW_FIELD_MARK)
    5687                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5688                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5689                 :            :                                 "mark, immediate value or a pointer to it"
    5690                 :            :                                 " cannot be used as a destination");
    5691   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_START ||
    5692                 :            :             src_data->field == RTE_FLOW_FIELD_START)
    5693                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5694                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5695                 :            :                                 "modifications of an arbitrary"
    5696                 :            :                                 " place in a packet is not supported");
    5697   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_VLAN_TYPE ||
    5698                 :            :             src_data->field == RTE_FLOW_FIELD_VLAN_TYPE)
    5699                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5700                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5701                 :            :                                 "modifications of the 802.1Q Tag"
    5702                 :            :                                 " Identifier is not supported");
    5703   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_VXLAN_VNI ||
    5704                 :            :             src_data->field == RTE_FLOW_FIELD_VXLAN_VNI)
    5705                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5706                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5707                 :            :                                 "modifications of the VXLAN Network"
    5708                 :            :                                 " Identifier is not supported");
    5709   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_VNI ||
    5710                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_VNI)
    5711                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5712                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5713                 :            :                                 "modifications of the GENEVE Network"
    5714                 :            :                                 " Identifier is not supported");
    5715   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE ||
    5716                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_TYPE)
    5717                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5718                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5719                 :            :                                 "modifications of the GENEVE option type is not supported");
    5720   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS ||
    5721                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_CLASS)
    5722                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5723                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5724                 :            :                                 "modifications of the GENEVE option class is not supported");
    5725   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_GENEVE_OPT_DATA ||
    5726                 :            :             src_data->field == RTE_FLOW_FIELD_GENEVE_OPT_DATA)
    5727                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5728                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5729                 :            :                                 "modifications of the GENEVE option data is not supported");
    5730   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_MPLS ||
    5731                 :            :             src_data->field == RTE_FLOW_FIELD_MPLS)
    5732                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5733                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5734                 :            :                                 "modifications of the MPLS header "
    5735                 :            :                                 "is not supported");
    5736   [ #  #  #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_RANDOM ||
    5737                 :            :             src_data->field == RTE_FLOW_FIELD_RANDOM)
    5738                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5739                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5740                 :            :                                 "modifications of random value is not supported");
    5741         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_MARK ||
    5742                 :            :             src_data->field == RTE_FLOW_FIELD_MARK)
    5743   [ #  #  #  # ]:          0 :                 if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
    5744                 :          0 :                     !mlx5_flow_ext_mreg_supported(dev))
    5745                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5746                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5747                 :            :                                         "cannot modify mark in legacy mode"
    5748                 :            :                                         " or without extensive registers");
    5749         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_META ||
    5750         [ #  # ]:          0 :             src_data->field == RTE_FLOW_FIELD_META) {
    5751   [ #  #  #  # ]:          0 :                 if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    5752                 :          0 :                     !mlx5_flow_ext_mreg_supported(dev))
    5753                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5754                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5755                 :            :                                         "cannot modify meta without"
    5756                 :            :                                         " extensive registers support");
    5757                 :          0 :                 ret = flow_dv_get_metadata_reg(dev, attr, error);
    5758         [ #  # ]:          0 :                 if (ret < 0 || ret == REG_NON)
    5759                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5760                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5761                 :            :                                         "cannot modify meta without"
    5762                 :            :                                         " extensive registers available");
    5763                 :            :         }
    5764         [ #  # ]:          0 :         if (conf->operation == RTE_FLOW_MODIFY_SUB)
    5765                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5766                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5767                 :            :                                 "sub operations are not supported");
    5768         [ #  # ]:          0 :         if (dst_data->field == RTE_FLOW_FIELD_IPV4_ECN ||
    5769   [ #  #  #  # ]:          0 :             src_data->field == RTE_FLOW_FIELD_IPV4_ECN ||
    5770         [ #  # ]:          0 :             dst_data->field == RTE_FLOW_FIELD_IPV6_ECN ||
    5771                 :            :             src_data->field == RTE_FLOW_FIELD_IPV6_ECN)
    5772   [ #  #  #  # ]:          0 :                 if (!hca_attr->modify_outer_ip_ecn && root)
    5773                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    5774                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, action,
    5775                 :            :                                 "modifications of the ECN for current firmware is not supported");
    5776                 :          0 :         return (width / 32) + !!(width % 32);
    5777                 :            : }
    5778                 :            : 
    5779                 :            : /**
    5780                 :            :  * Validate jump action.
    5781                 :            :  *
    5782                 :            :  * @param[in] action
    5783                 :            :  *   Pointer to the jump action.
    5784                 :            :  * @param[in] action_flags
    5785                 :            :  *   Holds the actions detected until now.
    5786                 :            :  * @param[in] attributes
    5787                 :            :  *   Pointer to flow attributes
    5788                 :            :  * @param[in] external
    5789                 :            :  *   Action belongs to flow rule created by request external to PMD.
    5790                 :            :  * @param[out] error
    5791                 :            :  *   Pointer to error structure.
    5792                 :            :  *
    5793                 :            :  * @return
    5794                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5795                 :            :  */
    5796                 :            : static int
    5797                 :          0 : flow_dv_validate_action_jump(struct rte_eth_dev *dev,
    5798                 :            :                              const struct mlx5_flow_tunnel *tunnel,
    5799                 :            :                              const struct rte_flow_action *action,
    5800                 :            :                              uint64_t action_flags,
    5801                 :            :                              const struct rte_flow_attr *attributes,
    5802                 :            :                              bool external, struct rte_flow_error *error)
    5803                 :            : {
    5804                 :          0 :         uint32_t target_group, table = 0;
    5805                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5806                 :            :         int ret = 0;
    5807                 :          0 :         struct flow_grp_info grp_info = {
    5808                 :            :                 .external = !!external,
    5809                 :          0 :                 .transfer = !!attributes->transfer,
    5810                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
    5811                 :            :                 .std_tbl_fix = 0
    5812                 :            :         };
    5813         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
    5814                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    5815                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5816                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5817                 :            :                                           "can't have 2 fate actions in"
    5818                 :            :                                           " same flow");
    5819         [ #  # ]:          0 :         if (!action->conf)
    5820                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5821                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5822                 :            :                                           NULL, "action configuration not set");
    5823                 :          0 :         target_group =
    5824                 :            :                 ((const struct rte_flow_action_jump *)action->conf)->group;
    5825                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, target_group, &table,
    5826                 :            :                                        &grp_info, error);
    5827         [ #  # ]:          0 :         if (ret)
    5828                 :            :                 return ret;
    5829         [ #  # ]:          0 :         if (table == 0)
    5830                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5831                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5832                 :            :                                           NULL, "root table shouldn't be destination");
    5833                 :            :         return 0;
    5834                 :            : }
    5835                 :            : 
    5836                 :            : /*
    5837                 :            :  * Validate action PORT_ID / REPRESENTED_PORT.
    5838                 :            :  *
    5839                 :            :  * @param[in] dev
    5840                 :            :  *   Pointer to rte_eth_dev structure.
    5841                 :            :  * @param[in] action_flags
    5842                 :            :  *   Bit-fields that holds the actions detected until now.
    5843                 :            :  * @param[in] action
    5844                 :            :  *   PORT_ID / REPRESENTED_PORT action structure.
    5845                 :            :  * @param[in] attr
    5846                 :            :  *   Attributes of flow that includes this action.
    5847                 :            :  * @param[out] error
    5848                 :            :  *   Pointer to error structure.
    5849                 :            :  *
    5850                 :            :  * @return
    5851                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5852                 :            :  */
    5853                 :            : static int
    5854                 :          0 : flow_dv_validate_action_port_id(struct rte_eth_dev *dev,
    5855                 :            :                                 uint64_t action_flags,
    5856                 :            :                                 const struct rte_flow_action *action,
    5857                 :            :                                 const struct rte_flow_attr *attr,
    5858                 :            :                                 struct rte_flow_error *error)
    5859                 :            : {
    5860                 :            :         const struct rte_flow_action_port_id *port_id;
    5861                 :            :         const struct rte_flow_action_ethdev *ethdev;
    5862                 :            :         struct mlx5_priv *act_priv;
    5863                 :            :         struct mlx5_priv *dev_priv;
    5864                 :            :         uint16_t port;
    5865                 :            : 
    5866         [ #  # ]:          0 :         if (!attr->transfer)
    5867                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5868                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5869                 :            :                                           NULL,
    5870                 :            :                                           "port action is valid in transfer"
    5871                 :            :                                           " mode only");
    5872   [ #  #  #  # ]:          0 :         if (!action || !action->conf)
    5873                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5874                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION_CONF,
    5875                 :            :                                           NULL,
    5876                 :            :                                           "port action parameters must be"
    5877                 :            :                                           " specified");
    5878         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
    5879                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    5880                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5881                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5882                 :            :                                           "can have only one fate actions in"
    5883                 :            :                                           " a flow");
    5884                 :          0 :         dev_priv = mlx5_dev_to_eswitch_info(dev);
    5885         [ #  # ]:          0 :         if (!dev_priv)
    5886                 :          0 :                 return rte_flow_error_set(error, rte_errno,
    5887                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5888                 :            :                                           NULL,
    5889                 :            :                                           "failed to obtain E-Switch info");
    5890      [ #  #  # ]:          0 :         switch (action->type) {
    5891                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID:
    5892                 :          0 :                 port_id = action->conf;
    5893         [ #  # ]:          0 :                 port = port_id->original ? dev->data->port_id : port_id->id;
    5894                 :            :                 break;
    5895                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    5896                 :          0 :                 ethdev = action->conf;
    5897                 :          0 :                 port = ethdev->port_id;
    5898                 :          0 :                 break;
    5899                 :          0 :         default:
    5900                 :            :                 MLX5_ASSERT(false);
    5901                 :          0 :                 return rte_flow_error_set
    5902                 :            :                                 (error, EINVAL,
    5903                 :            :                                  RTE_FLOW_ERROR_TYPE_ACTION, action,
    5904                 :            :                                  "unknown E-Switch action");
    5905                 :            :         }
    5906                 :          0 :         act_priv = mlx5_port_to_eswitch_info(port, false);
    5907         [ #  # ]:          0 :         if (!act_priv)
    5908                 :          0 :                 return rte_flow_error_set
    5909                 :            :                                 (error, rte_errno,
    5910                 :          0 :                                  RTE_FLOW_ERROR_TYPE_ACTION_CONF, action->conf,
    5911                 :            :                                  "failed to obtain E-Switch port id for port");
    5912         [ #  # ]:          0 :         if (act_priv->domain_id != dev_priv->domain_id)
    5913                 :          0 :                 return rte_flow_error_set
    5914                 :            :                                 (error, EINVAL,
    5915                 :            :                                  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5916                 :            :                                  "port does not belong to"
    5917                 :            :                                  " E-Switch being configured");
    5918                 :            :         return 0;
    5919                 :            : }
    5920                 :            : 
    5921                 :            : /**
    5922                 :            :  * Get the maximum number of modify header actions.
    5923                 :            :  *
    5924                 :            :  * @param dev
    5925                 :            :  *   Pointer to rte_eth_dev structure.
    5926                 :            :  * @param root
    5927                 :            :  *   Whether action is on root table.
    5928                 :            :  *
    5929                 :            :  * @return
    5930                 :            :  *   Max number of modify header actions device can support.
    5931                 :            :  */
    5932                 :            : static inline unsigned int
    5933                 :            : flow_dv_modify_hdr_action_max(struct rte_eth_dev *dev __rte_unused,
    5934                 :            :                               bool root)
    5935                 :            : {
    5936                 :            :         /*
    5937                 :            :          * There's no way to directly query the max capacity from FW.
    5938                 :            :          * The maximal value on root table should be assumed to be supported.
    5939                 :            :          */
    5940         [ #  # ]:          0 :         if (!root)
    5941                 :            :                 return MLX5_MAX_MODIFY_NUM;
    5942                 :            :         else
    5943                 :          0 :                 return MLX5_ROOT_TBL_MODIFY_NUM;
    5944                 :            : }
    5945                 :            : 
    5946                 :            : /**
    5947                 :            :  * Validate the meter action.
    5948                 :            :  *
    5949                 :            :  * @param[in] dev
    5950                 :            :  *   Pointer to rte_eth_dev structure.
    5951                 :            :  * @param[in] action_flags
    5952                 :            :  *   Bit-fields that holds the actions detected until now.
    5953                 :            :  * @param[in] item_flags
    5954                 :            :  *   Holds the items detected.
    5955                 :            :  * @param[in] action
    5956                 :            :  *   Pointer to the meter action.
    5957                 :            :  * @param[in] attr
    5958                 :            :  *   Attributes of flow that includes this action.
    5959                 :            :  * @param[in] port_id_item
    5960                 :            :  *   Pointer to item indicating port id.
    5961                 :            :  * @param[out] error
    5962                 :            :  *   Pointer to error structure.
    5963                 :            :  *
    5964                 :            :  * @return
    5965                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    5966                 :            :  */
    5967                 :            : static int
    5968                 :          0 : mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,
    5969                 :            :                                 uint64_t action_flags, uint64_t item_flags,
    5970                 :            :                                 const struct rte_flow_action *action,
    5971                 :            :                                 const struct rte_flow_attr *attr,
    5972                 :            :                                 const struct rte_flow_item *port_id_item,
    5973                 :            :                                 bool *def_policy,
    5974                 :            :                                 struct rte_flow_error *error)
    5975                 :            : {
    5976                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    5977                 :          0 :         const struct rte_flow_action_meter *am = action->conf;
    5978                 :            :         struct mlx5_flow_meter_info *fm;
    5979                 :            :         struct mlx5_flow_meter_policy *mtr_policy;
    5980                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
    5981                 :          0 :         uint16_t flow_src_port = priv->representor_id;
    5982                 :          0 :         bool all_ports = false;
    5983                 :            : 
    5984         [ #  # ]:          0 :         if (!am)
    5985                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5986                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5987                 :            :                                           "meter action conf is NULL");
    5988                 :            : 
    5989         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_METER)
    5990                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5991                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5992                 :            :                                           "meter chaining not support");
    5993         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_JUMP)
    5994                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5995                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5996                 :            :                                           "meter with jump not support");
    5997         [ #  # ]:          0 :         if (!priv->mtr_en)
    5998                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5999                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6000                 :            :                                           NULL,
    6001                 :            :                                           "meter action not supported");
    6002                 :          0 :         fm = mlx5_flow_meter_find(priv, am->mtr_id, NULL);
    6003         [ #  # ]:          0 :         if (!fm)
    6004                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6005                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6006                 :            :                                           "Meter not found");
    6007                 :            :         /* aso meter can always be shared by different domains */
    6008   [ #  #  #  # ]:          0 :         if (fm->ref_cnt && !priv->sh->meter_aso_en &&
    6009         [ #  # ]:          0 :             !(fm->transfer == attr->transfer ||
    6010   [ #  #  #  # ]:          0 :               (!fm->ingress && !attr->ingress && attr->egress) ||
    6011   [ #  #  #  # ]:          0 :               (!fm->egress && !attr->egress && attr->ingress)))
    6012                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6013                 :            :                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6014                 :            :                         "Flow attributes domain are either invalid "
    6015                 :            :                         "or have a domain conflict with current "
    6016                 :            :                         "meter attributes");
    6017         [ #  # ]:          0 :         if (fm->def_policy) {
    6018         [ #  # ]:          0 :                 if (!((attr->transfer &&
    6019         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_TRANSFER]) ||
    6020         [ #  # ]:          0 :                         (attr->egress &&
    6021         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_EGRESS]) ||
    6022         [ #  # ]:          0 :                         (attr->ingress &&
    6023         [ #  # ]:          0 :                         mtrmng->def_policy[MLX5_MTR_DOMAIN_INGRESS])))
    6024                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6025                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6026                 :            :                                           "Flow attributes domain "
    6027                 :            :                                           "have a conflict with current "
    6028                 :            :                                           "meter domain attributes");
    6029                 :          0 :                 *def_policy = true;
    6030                 :            :         } else {
    6031                 :          0 :                 mtr_policy = mlx5_flow_meter_policy_find(dev,
    6032                 :            :                                                 fm->policy_id, NULL);
    6033         [ #  # ]:          0 :                 if (!mtr_policy)
    6034                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6035                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6036                 :            :                                           "Invalid policy id for meter ");
    6037   [ #  #  #  # ]:          0 :                 if (!((attr->transfer && mtr_policy->transfer) ||
    6038   [ #  #  #  # ]:          0 :                         (attr->egress && mtr_policy->egress) ||
    6039   [ #  #  #  # ]:          0 :                         (attr->ingress && mtr_policy->ingress)))
    6040                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6041                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6042                 :            :                                           "Flow attributes domain "
    6043                 :            :                                           "have a conflict with current "
    6044                 :            :                                           "meter domain attributes");
    6045         [ #  # ]:          0 :                 if (port_id_item) {
    6046         [ #  # ]:          0 :                         if (mlx5_flow_get_item_vport_id(dev, port_id_item, &flow_src_port,
    6047                 :            :                                                         &all_ports, error))
    6048                 :          0 :                                 return -rte_errno;
    6049                 :            :                 }
    6050         [ #  # ]:          0 :                 if (attr->transfer) {
    6051                 :            :                         /* When flow matching all src ports, meter should not have drop count. */
    6052   [ #  #  #  #  :          0 :                         if (all_ports && (fm->drop_cnt || mtr_policy->hierarchy_match_port))
                   #  # ]
    6053                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6054                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
    6055                 :            :                                                           "Meter drop count or "
    6056                 :            :                                                           "modify_field/set_tag in meter hierarchy "
    6057                 :            :                                                           "not supported when matching all ports.");
    6058         [ #  # ]:          0 :                 } else if (mtr_policy->is_rss) {
    6059                 :            :                         struct mlx5_flow_meter_policy *fp;
    6060                 :            :                         struct mlx5_meter_policy_action_container *acg;
    6061                 :            :                         struct mlx5_meter_policy_action_container *acy;
    6062                 :            :                         const struct rte_flow_action *rss_act;
    6063                 :            :                         int ret;
    6064                 :            : 
    6065                 :          0 :                         fp = mlx5_flow_meter_hierarchy_get_final_policy(dev,
    6066                 :            :                                                                 mtr_policy);
    6067         [ #  # ]:          0 :                         if (fp == NULL)
    6068                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    6069                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6070                 :            :                                                   "Unable to get the final "
    6071                 :            :                                                   "policy in the hierarchy");
    6072                 :            :                         acg = &fp->act_cnt[RTE_COLOR_GREEN];
    6073                 :            :                         acy = &fp->act_cnt[RTE_COLOR_YELLOW];
    6074                 :            :                         MLX5_ASSERT(acg->fate_action ==
    6075                 :            :                                     MLX5_FLOW_FATE_SHARED_RSS ||
    6076                 :            :                                     acy->fate_action ==
    6077                 :            :                                     MLX5_FLOW_FATE_SHARED_RSS);
    6078         [ #  # ]:          0 :                         if (acg->fate_action == MLX5_FLOW_FATE_SHARED_RSS)
    6079                 :          0 :                                 rss_act = acg->rss;
    6080                 :            :                         else
    6081                 :          0 :                                 rss_act = acy->rss;
    6082                 :          0 :                         ret = mlx5_flow_validate_action_rss(rss_act,
    6083                 :            :                                         action_flags, dev, attr,
    6084                 :            :                                         item_flags, error);
    6085         [ #  # ]:          0 :                         if (ret)
    6086                 :            :                                 return ret;
    6087                 :            :                 }
    6088                 :          0 :                 *def_policy = false;
    6089                 :            :         }
    6090                 :            :         return 0;
    6091                 :            : }
    6092                 :            : 
    6093                 :            : /**
    6094                 :            :  * Validate the age action.
    6095                 :            :  *
    6096                 :            :  * @param[in] action_flags
    6097                 :            :  *   Holds the actions detected until now.
    6098                 :            :  * @param[in] action
    6099                 :            :  *   Pointer to the age action.
    6100                 :            :  * @param[in] dev
    6101                 :            :  *   Pointer to the Ethernet device structure.
    6102                 :            :  * @param[out] error
    6103                 :            :  *   Pointer to error structure.
    6104                 :            :  *
    6105                 :            :  * @return
    6106                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6107                 :            :  */
    6108                 :            : static int
    6109                 :          0 : flow_dv_validate_action_age(uint64_t action_flags,
    6110                 :            :                             const struct rte_flow_action *action,
    6111                 :            :                             struct rte_eth_dev *dev,
    6112                 :            :                             struct rte_flow_error *error)
    6113                 :            : {
    6114                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6115                 :          0 :         const struct rte_flow_action_age *age = action->conf;
    6116                 :            : 
    6117         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx ||
    6118   [ #  #  #  # ]:          0 :             (priv->sh->sws_cmng.counter_fallback && !priv->sh->aso_age_mng))
    6119                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6120                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6121                 :            :                                           NULL,
    6122                 :            :                                           "age action not supported");
    6123         [ #  # ]:          0 :         if (!(action->conf))
    6124                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6125                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6126                 :            :                                           "configuration cannot be null");
    6127         [ #  # ]:          0 :         if (!(age->timeout))
    6128                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6129                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6130                 :            :                                           "invalid timeout value 0");
    6131         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_AGE)
    6132                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6133                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6134                 :            :                                           "duplicate age actions set");
    6135                 :            :         return 0;
    6136                 :            : }
    6137                 :            : 
    6138                 :            : /**
    6139                 :            :  * Validate the modify-header IPv4 DSCP actions.
    6140                 :            :  *
    6141                 :            :  * @param[in] action_flags
    6142                 :            :  *   Holds the actions detected until now.
    6143                 :            :  * @param[in] action
    6144                 :            :  *   Pointer to the modify action.
    6145                 :            :  * @param[in] item_flags
    6146                 :            :  *   Holds the items detected.
    6147                 :            :  * @param[out] error
    6148                 :            :  *   Pointer to error structure.
    6149                 :            :  *
    6150                 :            :  * @return
    6151                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6152                 :            :  */
    6153                 :            : static int
    6154                 :          0 : flow_dv_validate_action_modify_ipv4_dscp(const uint64_t action_flags,
    6155                 :            :                                          const struct rte_flow_action *action,
    6156                 :            :                                          const uint64_t item_flags,
    6157                 :            :                                          struct rte_flow_error *error)
    6158                 :            : {
    6159                 :            :         int ret = 0;
    6160                 :            : 
    6161                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    6162         [ #  # ]:          0 :         if (!ret) {
    6163         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV4))
    6164                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6165                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6166                 :            :                                                   NULL,
    6167                 :            :                                                   "no ipv4 item in pattern");
    6168                 :            :         }
    6169                 :            :         return ret;
    6170                 :            : }
    6171                 :            : 
    6172                 :            : /**
    6173                 :            :  * Validate the modify-header IPv6 DSCP actions.
    6174                 :            :  *
    6175                 :            :  * @param[in] action_flags
    6176                 :            :  *   Holds the actions detected until now.
    6177                 :            :  * @param[in] action
    6178                 :            :  *   Pointer to the modify action.
    6179                 :            :  * @param[in] item_flags
    6180                 :            :  *   Holds the items detected.
    6181                 :            :  * @param[out] error
    6182                 :            :  *   Pointer to error structure.
    6183                 :            :  *
    6184                 :            :  * @return
    6185                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6186                 :            :  */
    6187                 :            : static int
    6188                 :          0 : flow_dv_validate_action_modify_ipv6_dscp(const uint64_t action_flags,
    6189                 :            :                                          const struct rte_flow_action *action,
    6190                 :            :                                          const uint64_t item_flags,
    6191                 :            :                                          struct rte_flow_error *error)
    6192                 :            : {
    6193                 :            :         int ret = 0;
    6194                 :            : 
    6195                 :          0 :         ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
    6196         [ #  # ]:          0 :         if (!ret) {
    6197         [ #  # ]:          0 :                 if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV6))
    6198                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6199                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6200                 :            :                                                   NULL,
    6201                 :            :                                                   "no ipv6 item in pattern");
    6202                 :            :         }
    6203                 :            :         return ret;
    6204                 :            : }
    6205                 :            : 
    6206                 :            : int
    6207                 :          0 : mlx5_flow_modify_match_cb(void *tool_ctx __rte_unused,
    6208                 :            :                           struct mlx5_list_entry *entry, void *cb_ctx)
    6209                 :            : {
    6210                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6211                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6212                 :            :         struct mlx5_flow_dv_modify_hdr_resource *resource =
    6213                 :            :                                   container_of(entry, typeof(*resource), entry);
    6214                 :            :         uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type);
    6215                 :            : 
    6216                 :          0 :         key_len += ref->actions_num * sizeof(ref->actions[0]);
    6217         [ #  # ]:          0 :         return ref->actions_num != resource->actions_num ||
    6218         [ #  # ]:          0 :                memcmp(&ref->ft_type, &resource->ft_type, key_len);
    6219                 :            : }
    6220                 :            : 
    6221                 :            : static struct mlx5_indexed_pool *
    6222                 :          0 : flow_dv_modify_ipool_get(struct mlx5_dev_ctx_shared *sh, uint8_t index)
    6223                 :            : {
    6224                 :          0 :         struct mlx5_indexed_pool *ipool = rte_atomic_load_explicit
    6225                 :            :                                      (&sh->mdh_ipools[index], rte_memory_order_seq_cst);
    6226                 :            : 
    6227         [ #  # ]:          0 :         if (!ipool) {
    6228                 :            :                 struct mlx5_indexed_pool *expected = NULL;
    6229                 :          0 :                 struct mlx5_indexed_pool_config cfg =
    6230                 :            :                     (struct mlx5_indexed_pool_config) {
    6231                 :          0 :                        .size = sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
    6232                 :          0 :                                                                    (index + 1) *
    6233                 :            :                                            sizeof(struct mlx5_modification_cmd),
    6234                 :            :                        .trunk_size = 64,
    6235                 :            :                        .grow_trunk = 3,
    6236                 :            :                        .grow_shift = 2,
    6237                 :            :                        .need_lock = 1,
    6238                 :          0 :                        .release_mem_en = !!sh->config.reclaim_mode,
    6239                 :            :                        .per_core_cache =
    6240         [ #  # ]:          0 :                                        sh->config.reclaim_mode ? 0 : (1 << 16),
    6241                 :            :                        .malloc = mlx5_malloc,
    6242                 :            :                        .free = mlx5_free,
    6243                 :            :                        .type = "mlx5_modify_action_resource",
    6244                 :            :                 };
    6245                 :            : 
    6246                 :          0 :                 cfg.size = RTE_ALIGN(cfg.size, sizeof(ipool));
    6247                 :          0 :                 ipool = mlx5_ipool_create(&cfg);
    6248         [ #  # ]:          0 :                 if (!ipool)
    6249                 :          0 :                         return NULL;
    6250         [ #  # ]:          0 :                 if (!rte_atomic_compare_exchange_strong_explicit(&sh->mdh_ipools[index],
    6251                 :            :                                                  &expected, ipool,
    6252                 :            :                                                  rte_memory_order_seq_cst,
    6253                 :            :                                                  rte_memory_order_seq_cst)) {
    6254                 :          0 :                         mlx5_ipool_destroy(ipool);
    6255                 :          0 :                         ipool = rte_atomic_load_explicit(&sh->mdh_ipools[index],
    6256                 :            :                                                 rte_memory_order_seq_cst);
    6257                 :            :                 }
    6258                 :            :         }
    6259                 :            :         return ipool;
    6260                 :            : }
    6261                 :            : 
    6262                 :            : struct mlx5_list_entry *
    6263                 :          0 : mlx5_flow_modify_create_cb(void *tool_ctx, void *cb_ctx)
    6264                 :            : {
    6265                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6266                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6267                 :            :         struct mlx5dv_dr_domain *ns;
    6268                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry;
    6269                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6270                 :          0 :         struct mlx5_indexed_pool *ipool = flow_dv_modify_ipool_get(sh,
    6271                 :          0 :                                                           ref->actions_num - 1);
    6272                 :            :         int ret = 0;
    6273                 :          0 :         uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]);
    6274                 :            :         uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type);
    6275                 :            :         uint32_t idx;
    6276                 :            : 
    6277         [ #  # ]:          0 :         if (unlikely(!ipool)) {
    6278                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6279                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6280                 :            :                                    NULL, "cannot allocate modify ipool");
    6281                 :          0 :                 return NULL;
    6282                 :            :         }
    6283                 :          0 :         entry = mlx5_ipool_zmalloc(ipool, &idx);
    6284         [ #  # ]:          0 :         if (!entry) {
    6285                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6286                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6287                 :            :                                    "cannot allocate resource memory");
    6288                 :          0 :                 return NULL;
    6289                 :            :         }
    6290                 :          0 :         rte_memcpy(&entry->ft_type,
    6291                 :          0 :                         RTE_PTR_ADD(ref, offsetof(typeof(*ref), ft_type)),
    6292         [ #  # ]:          0 :                         key_len + data_len);
    6293         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2) {
    6294                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
    6295                 :          0 :                 struct mlx5dr_action_mh_pattern pattern = {
    6296                 :            :                         .sz = data_len,
    6297                 :          0 :                         .data = (rte_be64_t *)ref->actions
    6298                 :            :                 };
    6299                 :          0 :                 entry->action = mlx5dr_action_create_modify_header(ctx->data2,
    6300                 :            :                         1,
    6301                 :          0 :                         &pattern, 0, ref->flags);
    6302         [ #  # ]:          0 :                 if (!entry->action)
    6303                 :            :                         ret = -1;
    6304                 :            : #else
    6305                 :            :                 ret = -1;
    6306                 :            : #endif
    6307                 :            :         } else {
    6308         [ #  # ]:          0 :                 if (entry->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
    6309                 :          0 :                         ns = sh->fdb_domain;
    6310         [ #  # ]:          0 :                 else if (entry->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX)
    6311                 :          0 :                         ns = sh->tx_domain;
    6312                 :            :                 else
    6313                 :          0 :                         ns = sh->rx_domain;
    6314                 :          0 :                 ret = mlx5_flow_os_create_flow_action_modify_header
    6315                 :          0 :                                                 (sh->cdev->ctx, ns, entry,
    6316                 :            :                                                 data_len, &entry->action);
    6317                 :            :         }
    6318                 :            :         if (ret) {
    6319                 :          0 :                 mlx5_ipool_free(sh->mdh_ipools[ref->actions_num - 1], idx);
    6320                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6321                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6322                 :            :                                    NULL, "cannot create modification action");
    6323                 :          0 :                 return NULL;
    6324                 :            :         }
    6325                 :          0 :         entry->idx = idx;
    6326                 :          0 :         return &entry->entry;
    6327                 :            : }
    6328                 :            : 
    6329                 :            : struct mlx5_list_entry *
    6330                 :          0 : mlx5_flow_modify_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
    6331                 :            :                           void *cb_ctx)
    6332                 :            : {
    6333                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6334                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
    6335                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry;
    6336                 :          0 :         struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
    6337                 :          0 :         uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]);
    6338                 :            :         uint32_t idx;
    6339                 :            : 
    6340                 :          0 :         entry = mlx5_ipool_malloc(sh->mdh_ipools[ref->actions_num - 1],
    6341                 :            :                                   &idx);
    6342         [ #  # ]:          0 :         if (!entry) {
    6343                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
    6344                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    6345                 :            :                                    "cannot allocate resource memory");
    6346                 :          0 :                 return NULL;
    6347                 :            :         }
    6348                 :          0 :         memcpy(entry, oentry, sizeof(*entry) + data_len);
    6349                 :          0 :         entry->idx = idx;
    6350                 :          0 :         return &entry->entry;
    6351                 :            : }
    6352                 :            : 
    6353                 :            : void
    6354                 :          0 : mlx5_flow_modify_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
    6355                 :            : {
    6356                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
    6357                 :            :         struct mlx5_flow_dv_modify_hdr_resource *res =
    6358                 :            :                 container_of(entry, typeof(*res), entry);
    6359                 :            : 
    6360                 :          0 :         mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
    6361                 :          0 : }
    6362                 :            : 
    6363                 :            : /**
    6364                 :            :  * Validate the sample action.
    6365                 :            :  *
    6366                 :            :  * @param[in, out] action_flags
    6367                 :            :  *   Holds the actions detected until now.
    6368                 :            :  * @param[in] action
    6369                 :            :  *   Pointer to the sample action.
    6370                 :            :  * @param[in] dev
    6371                 :            :  *   Pointer to the Ethernet device structure.
    6372                 :            :  * @param[in] attr
    6373                 :            :  *   Attributes of flow that includes this action.
    6374                 :            :  * @param[in] item_flags
    6375                 :            :  *   Holds the items detected.
    6376                 :            :  * @param[in] rss
    6377                 :            :  *   Pointer to the RSS action.
    6378                 :            :  * @param[out] sample_rss
    6379                 :            :  *   Pointer to the RSS action in sample action list.
    6380                 :            :  * @param[out] count
    6381                 :            :  *   Pointer to the COUNT action in sample action list.
    6382                 :            :  * @param[out] fdb_mirror
    6383                 :            :  *   Pointer to the FDB mirror flag.
    6384                 :            :  * @param root
    6385                 :            :  *   Whether action is on root table.
    6386                 :            :  * @param[out] error
    6387                 :            :  *   Pointer to error structure.
    6388                 :            :  *
    6389                 :            :  * @return
    6390                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    6391                 :            :  */
    6392                 :            : static int
    6393                 :          0 : flow_dv_validate_action_sample(uint64_t *action_flags,
    6394                 :            :                                uint64_t *sub_action_flags,
    6395                 :            :                                const struct rte_flow_action *action,
    6396                 :            :                                struct rte_eth_dev *dev,
    6397                 :            :                                const struct rte_flow_attr *attr,
    6398                 :            :                                uint64_t item_flags,
    6399                 :            :                                const struct rte_flow_action_rss *rss,
    6400                 :            :                                const struct rte_flow_action_rss **sample_rss,
    6401                 :            :                                const struct rte_flow_action_count **count,
    6402                 :            :                                int *fdb_mirror,
    6403                 :            :                                uint16_t *sample_port_id,
    6404                 :            :                                bool root,
    6405                 :            :                                struct rte_flow_error *error)
    6406                 :            : {
    6407                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6408                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
    6409                 :          0 :         const struct rte_flow_action_sample *sample = action->conf;
    6410                 :            :         const struct rte_flow_action_port_id *port = NULL;
    6411                 :            :         const struct rte_flow_action *act;
    6412                 :            :         uint16_t queue_index = 0xFFFF;
    6413                 :          0 :         int actions_n = 0;
    6414                 :            :         int ret;
    6415                 :            : 
    6416         [ #  # ]:          0 :         if (!sample)
    6417                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6418                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6419                 :            :                                           "configuration cannot be NULL");
    6420         [ #  # ]:          0 :         if (sample->ratio == 0)
    6421                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6422                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6423                 :            :                                           "ratio value starts from 1");
    6424         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx ||
    6425         [ #  # ]:          0 :             (sample->ratio > 0 && !priv->sampler_en))
    6426                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6427                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6428                 :            :                                           NULL,
    6429                 :            :                                           "sample action not supported");
    6430         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_SAMPLE)
    6431                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6432                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6433                 :            :                                           "Multiple sample actions not "
    6434                 :            :                                           "supported");
    6435         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_METER)
    6436                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6437                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6438                 :            :                                           "wrong action order, meter should "
    6439                 :            :                                           "be after sample action");
    6440         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_JUMP)
    6441                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6442                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6443                 :            :                                           "wrong action order, jump should "
    6444                 :            :                                           "be after sample action");
    6445         [ #  # ]:          0 :         if (*action_flags & MLX5_FLOW_ACTION_CT)
    6446                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    6447                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
    6448                 :            :                                           "Sample after CT not supported");
    6449                 :          0 :         act = sample->actions;
    6450         [ #  # ]:          0 :         for (; act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
    6451         [ #  # ]:          0 :                 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
    6452                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6453                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6454                 :            :                                                   act, "too many actions");
    6455   [ #  #  #  #  :          0 :                 switch (act->type) {
             #  #  #  # ]
    6456                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    6457                 :          0 :                         ret = mlx5_flow_validate_action_queue(act,
    6458                 :            :                                                               *sub_action_flags,
    6459                 :            :                                                               dev,
    6460                 :            :                                                               attr, error);
    6461         [ #  # ]:          0 :                         if (ret < 0)
    6462                 :          0 :                                 return ret;
    6463                 :          0 :                         queue_index = ((const struct rte_flow_action_queue *)
    6464                 :          0 :                                                         (act->conf))->index;
    6465                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_QUEUE;
    6466                 :          0 :                         ++actions_n;
    6467                 :          0 :                         break;
    6468                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    6469                 :          0 :                         *sample_rss = act->conf;
    6470                 :          0 :                         ret = mlx5_flow_validate_action_rss(act,
    6471                 :            :                                                             *sub_action_flags,
    6472                 :            :                                                             dev, attr,
    6473                 :            :                                                             item_flags,
    6474                 :            :                                                             error);
    6475         [ #  # ]:          0 :                         if (ret < 0)
    6476                 :          0 :                                 return ret;
    6477   [ #  #  #  # ]:          0 :                         if (rss && *sample_rss &&
    6478         [ #  # ]:          0 :                             ((*sample_rss)->level != rss->level ||
    6479         [ #  # ]:          0 :                             (*sample_rss)->types != rss->types))
    6480                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    6481                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    6482                 :            :                                         NULL,
    6483                 :            :                                         "Can't use the different RSS types "
    6484                 :            :                                         "or level in the same flow");
    6485   [ #  #  #  # ]:          0 :                         if (*sample_rss != NULL && (*sample_rss)->queue_num)
    6486                 :          0 :                                 queue_index = (*sample_rss)->queue[0];
    6487                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_RSS;
    6488                 :          0 :                         ++actions_n;
    6489                 :          0 :                         break;
    6490                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    6491                 :          0 :                         ret = flow_dv_validate_action_mark(dev, act,
    6492                 :            :                                                            *sub_action_flags,
    6493                 :            :                                                            attr, error);
    6494         [ #  # ]:          0 :                         if (ret < 0)
    6495                 :          0 :                                 return ret;
    6496         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY)
    6497                 :          0 :                                 *sub_action_flags |= MLX5_FLOW_ACTION_MARK |
    6498                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    6499                 :            :                         else
    6500                 :          0 :                                 *sub_action_flags |= MLX5_FLOW_ACTION_MARK;
    6501                 :          0 :                         ++actions_n;
    6502                 :          0 :                         break;
    6503                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    6504                 :          0 :                         ret = flow_dv_validate_action_count
    6505                 :          0 :                                 (dev, false, *action_flags | *sub_action_flags,
    6506                 :            :                                  root, error);
    6507         [ #  # ]:          0 :                         if (ret < 0)
    6508                 :          0 :                                 return ret;
    6509                 :          0 :                         *count = act->conf;
    6510                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_COUNT;
    6511                 :          0 :                         *action_flags |= MLX5_FLOW_ACTION_COUNT;
    6512                 :          0 :                         ++actions_n;
    6513                 :          0 :                         break;
    6514                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
    6515                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    6516                 :          0 :                         ret = flow_dv_validate_action_port_id(dev,
    6517                 :            :                                                               *sub_action_flags,
    6518                 :            :                                                               act,
    6519                 :            :                                                               attr,
    6520                 :            :                                                               error);
    6521         [ #  # ]:          0 :                         if (ret)
    6522                 :          0 :                                 return ret;
    6523         [ #  # ]:          0 :                         if (act->type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
    6524                 :          0 :                                 port = (const struct rte_flow_action_port_id *)
    6525                 :            :                                         act->conf;
    6526         [ #  # ]:          0 :                                 *sample_port_id = port->original ?
    6527                 :          0 :                                                   dev->data->port_id : port->id;
    6528                 :            :                         } else {
    6529                 :          0 :                                 *sample_port_id = ((const struct rte_flow_action_ethdev *)
    6530                 :          0 :                                                   act->conf)->port_id;
    6531                 :            :                         }
    6532                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_PORT_ID;
    6533                 :          0 :                         ++actions_n;
    6534                 :          0 :                         break;
    6535                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    6536                 :          0 :                         ret = mlx5_flow_dv_validate_action_raw_encap_decap
    6537                 :          0 :                                 (dev, NULL, act->conf, attr, sub_action_flags,
    6538                 :            :                                  &actions_n, action, item_flags, error);
    6539         [ #  # ]:          0 :                         if (ret < 0)
    6540                 :          0 :                                 return ret;
    6541                 :          0 :                         ++actions_n;
    6542                 :          0 :                         break;
    6543                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    6544                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    6545                 :          0 :                         ret = mlx5_flow_dv_validate_action_l2_encap(dev,
    6546                 :            :                                                                     *sub_action_flags,
    6547                 :            :                                                                     act, attr,
    6548                 :            :                                                                     error);
    6549         [ #  # ]:          0 :                         if (ret < 0)
    6550                 :          0 :                                 return ret;
    6551                 :          0 :                         *sub_action_flags |= MLX5_FLOW_ACTION_ENCAP;
    6552                 :          0 :                         ++actions_n;
    6553                 :          0 :                         break;
    6554                 :          0 :                 default:
    6555                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6556                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6557                 :            :                                                   NULL,
    6558                 :            :                                                   "Doesn't support optional "
    6559                 :            :                                                   "action");
    6560                 :            :                 }
    6561                 :            :         }
    6562         [ #  # ]:          0 :         if (attr->ingress) {
    6563         [ #  # ]:          0 :                 if (!(*sub_action_flags & (MLX5_FLOW_ACTION_QUEUE |
    6564                 :            :                                           MLX5_FLOW_ACTION_RSS)))
    6565                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6566                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6567                 :            :                                                   NULL,
    6568                 :            :                                                   "Ingress must has a dest "
    6569                 :            :                                                   "QUEUE for Sample");
    6570         [ #  # ]:          0 :         } else if (attr->egress) {
    6571                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    6572                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    6573                 :            :                                           NULL,
    6574                 :            :                                           "Sample Only support Ingress "
    6575                 :            :                                           "or E-Switch");
    6576         [ #  # ]:          0 :         } else if (sample->actions->type != RTE_FLOW_ACTION_TYPE_END) {
    6577                 :            :                 MLX5_ASSERT(attr->transfer);
    6578         [ #  # ]:          0 :                 if (sample->ratio > 1)
    6579                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6580                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6581                 :            :                                                   NULL,
    6582                 :            :                                                   "E-Switch doesn't support "
    6583                 :            :                                                   "any optional action "
    6584                 :            :                                                   "for sampling");
    6585         [ #  # ]:          0 :                 if (*sub_action_flags & MLX5_FLOW_ACTION_QUEUE)
    6586                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6587                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6588                 :            :                                                   NULL,
    6589                 :            :                                                   "unsupported action QUEUE");
    6590         [ #  # ]:          0 :                 if (*sub_action_flags & MLX5_FLOW_ACTION_RSS)
    6591                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6592                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6593                 :            :                                                   NULL,
    6594                 :            :                                                   "unsupported action QUEUE");
    6595         [ #  # ]:          0 :                 if (!(*sub_action_flags & MLX5_FLOW_ACTION_PORT_ID))
    6596                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    6597                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6598                 :            :                                                   NULL,
    6599                 :            :                                                   "E-Switch must has a dest "
    6600                 :            :                                                   "port for mirroring");
    6601                 :          0 :                 *fdb_mirror = 1;
    6602                 :            :         }
    6603                 :            :         /* Continue validation for Xcap actions.*/
    6604   [ #  #  #  # ]:          0 :         if ((*sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) &&
    6605         [ #  # ]:          0 :             (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index))) {
    6606         [ #  # ]:          0 :                 if ((*sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
    6607                 :            :                      MLX5_FLOW_XCAP_ACTIONS)
    6608                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6609                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6610                 :            :                                                   NULL, "encap and decap "
    6611                 :            :                                                   "combination aren't "
    6612                 :            :                                                   "supported");
    6613   [ #  #  #  # ]:          0 :                 if (attr->ingress && (*sub_action_flags & MLX5_FLOW_ACTION_ENCAP))
    6614                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    6615                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    6616                 :            :                                                   NULL, "encap is not supported"
    6617                 :            :                                                   " for ingress traffic");
    6618                 :            :         }
    6619                 :            :         return 0;
    6620                 :            : }
    6621                 :            : 
    6622                 :            : int
    6623                 :          0 : mlx5_flow_modify_hdr_resource_register(struct rte_eth_dev *dev,
    6624                 :            :                                        struct mlx5_flow_dv_modify_hdr_resource *resource,
    6625                 :            :                                        struct mlx5_flow_dv_modify_hdr_resource **modify,
    6626                 :            :                                        struct rte_flow_error *error)
    6627                 :            : {
    6628                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6629                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
    6630                 :          0 :         uint32_t key_len = sizeof(*resource) -
    6631                 :            :                            offsetof(typeof(*resource), ft_type) +
    6632                 :          0 :                            resource->actions_num * sizeof(resource->actions[0]);
    6633                 :            :         struct mlx5_list_entry *entry;
    6634                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
    6635                 :            :                 .error = error,
    6636                 :            :                 .data = resource,
    6637                 :          0 :                 .data2 = priv->dr_ctx,
    6638                 :            :         };
    6639                 :            :         struct mlx5_hlist *modify_cmds;
    6640                 :            :         uint64_t key64;
    6641                 :            : 
    6642                 :          0 :         modify_cmds = flow_dv_hlist_prepare(sh, &sh->modify_cmds,
    6643                 :            :                                 "hdr_modify",
    6644                 :            :                                 MLX5_FLOW_HDR_MODIFY_HTABLE_SZ,
    6645                 :            :                                 true, false, sh,
    6646                 :            :                                 mlx5_flow_modify_create_cb,
    6647                 :            :                                 mlx5_flow_modify_match_cb,
    6648                 :            :                                 mlx5_flow_modify_remove_cb,
    6649                 :            :                                 mlx5_flow_modify_clone_cb,
    6650                 :            :                                 mlx5_flow_modify_clone_free_cb,
    6651                 :            :                                 error);
    6652         [ #  # ]:          0 :         if (unlikely(!modify_cmds))
    6653                 :          0 :                 return -rte_errno;
    6654         [ #  # ]:          0 :         if (resource->actions_num > flow_dv_modify_hdr_action_max(dev,
    6655         [ #  # ]:          0 :                                                                 resource->root))
    6656                 :          0 :                 return rte_flow_error_set(error, EOVERFLOW,
    6657                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    6658                 :            :                                           "too many modify header items");
    6659                 :          0 :         key64 = __rte_raw_cksum(&resource->ft_type, key_len, 0);
    6660                 :          0 :         entry = mlx5_hlist_register(modify_cmds, key64, &ctx);
    6661         [ #  # ]:          0 :         if (!entry)
    6662                 :          0 :                 return -rte_errno;
    6663                 :          0 :         *modify = container_of(entry, typeof(*resource), entry);
    6664                 :          0 :         return 0;
    6665                 :            : }
    6666                 :            : 
    6667                 :            : /**
    6668                 :            :  * Find existing modify-header resource or create and register a new one.
    6669                 :            :  *
    6670                 :            :  * @param dev[in, out]
    6671                 :            :  *   Pointer to rte_eth_dev structure.
    6672                 :            :  * @param[in, out] resource
    6673                 :            :  *   Pointer to modify-header resource.
    6674                 :            :  * @param[in, out] dev_flow
    6675                 :            :  *   Pointer to the dev_flow.
    6676                 :            :  * @param[out] error
    6677                 :            :  *   pointer to error structure.
    6678                 :            :  *
    6679                 :            :  * @return
    6680                 :            :  *   0 on success otherwise -errno and errno is set.
    6681                 :            :  */
    6682                 :            : static int
    6683                 :            : flow_dv_modify_hdr_resource_register
    6684                 :            :                         (struct rte_eth_dev *dev,
    6685                 :            :                          struct mlx5_flow_dv_modify_hdr_resource *resource,
    6686                 :            :                          struct mlx5_flow *dev_flow,
    6687                 :            :                          struct rte_flow_error *error)
    6688                 :            : {
    6689                 :          0 :         resource->root = !dev_flow->dv.group;
    6690                 :          0 :         return mlx5_flow_modify_hdr_resource_register(dev, resource,
    6691                 :          0 :                                                       &dev_flow->handle->dvh.modify_hdr, error);
    6692                 :            : }
    6693                 :            : 
    6694                 :            : /**
    6695                 :            :  * Get DV flow counter by index.
    6696                 :            :  *
    6697                 :            :  * @param[in] dev
    6698                 :            :  *   Pointer to the Ethernet device structure.
    6699                 :            :  * @param[in] idx
    6700                 :            :  *   mlx5 flow counter index in the container.
    6701                 :            :  * @param[out] ppool
    6702                 :            :  *   mlx5 flow counter pool in the container.
    6703                 :            :  *
    6704                 :            :  * @return
    6705                 :            :  *   Pointer to the counter, NULL otherwise.
    6706                 :            :  */
    6707                 :            : static struct mlx5_flow_counter *
    6708                 :            : flow_dv_counter_get_by_idx(struct rte_eth_dev *dev,
    6709                 :            :                            uint32_t idx,
    6710                 :            :                            struct mlx5_flow_counter_pool **ppool)
    6711                 :            : {
    6712                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6713                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6714                 :            :         struct mlx5_flow_counter_pool *pool;
    6715                 :            : 
    6716                 :            :         /* Decrease to original index and clear shared bit. */
    6717                 :          0 :         idx = (idx - 1) & (MLX5_CNT_SHARED_OFFSET - 1);
    6718                 :            :         MLX5_ASSERT(idx / MLX5_COUNTERS_PER_POOL < MLX5_COUNTER_POOLS_MAX_NUM);
    6719                 :          0 :         pool = cmng->pools[idx / MLX5_COUNTERS_PER_POOL];
    6720                 :            :         MLX5_ASSERT(pool);
    6721                 :            :         if (ppool)
    6722                 :            :                 *ppool = pool;
    6723   [ #  #  #  #  :          0 :         return MLX5_POOL_GET_CNT(pool, idx % MLX5_COUNTERS_PER_POOL);
          #  #  #  #  #  
                #  #  # ]
    6724                 :            : }
    6725                 :            : 
    6726                 :            : /**
    6727                 :            :  * Check the devx counter belongs to the pool.
    6728                 :            :  *
    6729                 :            :  * @param[in] pool
    6730                 :            :  *   Pointer to the counter pool.
    6731                 :            :  * @param[in] id
    6732                 :            :  *   The counter devx ID.
    6733                 :            :  *
    6734                 :            :  * @return
    6735                 :            :  *   True if counter belongs to the pool, false otherwise.
    6736                 :            :  */
    6737                 :            : static bool
    6738                 :            : flow_dv_is_counter_in_pool(struct mlx5_flow_counter_pool *pool, int id)
    6739                 :            : {
    6740                 :          0 :         int base = (pool->min_dcs->id / MLX5_COUNTERS_PER_POOL) *
    6741                 :            :                    MLX5_COUNTERS_PER_POOL;
    6742                 :            : 
    6743   [ #  #  #  # ]:          0 :         if (id >= base && id < base + MLX5_COUNTERS_PER_POOL)
    6744                 :            :                 return true;
    6745                 :            :         return false;
    6746                 :            : }
    6747                 :            : 
    6748                 :            : /**
    6749                 :            :  * Get a pool by devx counter ID.
    6750                 :            :  *
    6751                 :            :  * @param[in] cmng
    6752                 :            :  *   Pointer to the counter management.
    6753                 :            :  * @param[in] id
    6754                 :            :  *   The counter devx ID.
    6755                 :            :  *
    6756                 :            :  * @return
    6757                 :            :  *   The counter pool pointer if exists, NULL otherwise,
    6758                 :            :  */
    6759                 :            : static struct mlx5_flow_counter_pool *
    6760                 :          0 : flow_dv_find_pool_by_id(struct mlx5_flow_counter_mng *cmng, int id)
    6761                 :            : {
    6762                 :            :         uint32_t i;
    6763                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6764                 :            : 
    6765                 :          0 :         rte_spinlock_lock(&cmng->pool_update_sl);
    6766                 :            :         /* Check last used pool. */
    6767         [ #  # ]:          0 :         if (cmng->last_pool_idx != POOL_IDX_INVALID &&
    6768         [ #  # ]:          0 :             flow_dv_is_counter_in_pool(cmng->pools[cmng->last_pool_idx], id)) {
    6769                 :            :                 pool = cmng->pools[cmng->last_pool_idx];
    6770                 :          0 :                 goto out;
    6771                 :            :         }
    6772                 :            :         /* ID out of range means no suitable pool in the container. */
    6773   [ #  #  #  # ]:          0 :         if (id > cmng->max_id || id < cmng->min_id)
    6774                 :          0 :                 goto out;
    6775                 :            :         /*
    6776                 :            :          * Find the pool from the end of the container, since mostly counter
    6777                 :            :          * ID is sequence increasing, and the last pool should be the needed
    6778                 :            :          * one.
    6779                 :            :          */
    6780                 :          0 :         i = cmng->n_valid;
    6781         [ #  # ]:          0 :         while (i--) {
    6782         [ #  # ]:          0 :                 struct mlx5_flow_counter_pool *pool_tmp = cmng->pools[i];
    6783                 :            : 
    6784                 :            :                 if (flow_dv_is_counter_in_pool(pool_tmp, id)) {
    6785                 :            :                         pool = pool_tmp;
    6786                 :            :                         break;
    6787                 :            :                 }
    6788                 :            :         }
    6789                 :          0 : out:
    6790                 :            :         rte_spinlock_unlock(&cmng->pool_update_sl);
    6791                 :          0 :         return pool;
    6792                 :            : }
    6793                 :            : 
    6794                 :            : /**
    6795                 :            :  * Query a devx flow counter.
    6796                 :            :  *
    6797                 :            :  * @param[in] dev
    6798                 :            :  *   Pointer to the Ethernet device structure.
    6799                 :            :  * @param[in] counter
    6800                 :            :  *   Index to the flow counter.
    6801                 :            :  * @param[out] pkts
    6802                 :            :  *   The statistics value of packets.
    6803                 :            :  * @param[out] bytes
    6804                 :            :  *   The statistics value of bytes.
    6805                 :            :  *
    6806                 :            :  * @return
    6807                 :            :  *   0 on success, otherwise a negative errno value and rte_errno is set.
    6808                 :            :  */
    6809                 :            : static inline int
    6810                 :          0 : _flow_dv_query_count(struct rte_eth_dev *dev, uint32_t counter, uint64_t *pkts,
    6811                 :            :                      uint64_t *bytes)
    6812                 :            : {
    6813         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6814                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6815                 :            :         struct mlx5_flow_counter *cnt;
    6816                 :            :         int offset;
    6817                 :            : 
    6818                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, &pool);
    6819                 :            :         MLX5_ASSERT(pool);
    6820         [ #  # ]:          0 :         if (priv->sh->sws_cmng.counter_fallback)
    6821                 :          0 :                 return mlx5_devx_cmd_flow_counter_query(cnt->dcs_when_active, 0,
    6822                 :            :                                         0, pkts, bytes, 0, NULL, NULL, 0);
    6823                 :          0 :         rte_spinlock_lock(&pool->sl);
    6824         [ #  # ]:          0 :         if (!pool->raw) {
    6825                 :          0 :                 *pkts = 0;
    6826                 :          0 :                 *bytes = 0;
    6827                 :            :         } else {
    6828         [ #  # ]:          0 :                 offset = MLX5_CNT_ARRAY_IDX(pool, cnt);
    6829                 :          0 :                 *pkts = rte_be_to_cpu_64(pool->raw->data[offset].hits);
    6830                 :          0 :                 *bytes = rte_be_to_cpu_64(pool->raw->data[offset].bytes);
    6831                 :            :         }
    6832                 :            :         rte_spinlock_unlock(&pool->sl);
    6833                 :          0 :         return 0;
    6834                 :            : }
    6835                 :            : 
    6836                 :            : /**
    6837                 :            :  * Create and initialize a new counter pool.
    6838                 :            :  *
    6839                 :            :  * @param[in] dev
    6840                 :            :  *   Pointer to the Ethernet device structure.
    6841                 :            :  * @param[out] dcs
    6842                 :            :  *   The devX counter handle.
    6843                 :            :  * @param[in] age
    6844                 :            :  *   Whether the pool is for counter that was allocated for aging.
    6845                 :            :  *
    6846                 :            :  * @return
    6847                 :            :  *   The pool container pointer on success, NULL otherwise and rte_errno is set.
    6848                 :            :  */
    6849                 :            : static struct mlx5_flow_counter_pool *
    6850                 :          0 : flow_dv_pool_create(struct rte_eth_dev *dev, struct mlx5_devx_obj *dcs,
    6851                 :            :                     uint32_t age)
    6852                 :            : {
    6853                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6854                 :            :         struct mlx5_flow_counter_pool *pool;
    6855                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6856                 :          0 :         bool fallback = cmng->counter_fallback;
    6857                 :            :         uint32_t size = sizeof(*pool);
    6858                 :            : 
    6859         [ #  # ]:          0 :         if (cmng->n_valid == MLX5_COUNTER_POOLS_MAX_NUM) {
    6860                 :          0 :                 DRV_LOG(ERR, "All counter is in used, try again later.");
    6861                 :          0 :                 rte_errno = EAGAIN;
    6862                 :          0 :                 return NULL;
    6863                 :            :         }
    6864                 :            :         size += MLX5_COUNTERS_PER_POOL * MLX5_CNT_SIZE;
    6865         [ #  # ]:          0 :         size += (!age ? 0 : MLX5_COUNTERS_PER_POOL * MLX5_AGE_SIZE);
    6866                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, size, 0, SOCKET_ID_ANY);
    6867         [ #  # ]:          0 :         if (!pool) {
    6868                 :          0 :                 rte_errno = ENOMEM;
    6869                 :          0 :                 return NULL;
    6870                 :            :         }
    6871                 :          0 :         pool->raw = NULL;
    6872                 :          0 :         pool->is_aged = !!age;
    6873                 :          0 :         pool->query_gen = 0;
    6874                 :          0 :         pool->min_dcs = dcs;
    6875                 :            :         rte_spinlock_init(&pool->sl);
    6876                 :            :         rte_spinlock_init(&pool->csl);
    6877                 :          0 :         TAILQ_INIT(&pool->counters[0]);
    6878                 :          0 :         TAILQ_INIT(&pool->counters[1]);
    6879                 :          0 :         pool->time_of_last_age_check = MLX5_CURR_TIME_SEC;
    6880                 :          0 :         rte_spinlock_lock(&cmng->pool_update_sl);
    6881                 :          0 :         pool->index = cmng->n_valid;
    6882                 :          0 :         cmng->pools[pool->index] = pool;
    6883                 :          0 :         cmng->n_valid++;
    6884         [ #  # ]:          0 :         if (unlikely(fallback)) {
    6885                 :          0 :                 int base = RTE_ALIGN_FLOOR(dcs->id, MLX5_COUNTERS_PER_POOL);
    6886                 :            : 
    6887         [ #  # ]:          0 :                 if (base < cmng->min_id)
    6888                 :          0 :                         cmng->min_id = base;
    6889         [ #  # ]:          0 :                 if (base > cmng->max_id)
    6890                 :          0 :                         cmng->max_id = base + MLX5_COUNTERS_PER_POOL - 1;
    6891                 :          0 :                 cmng->last_pool_idx = pool->index;
    6892                 :            :         }
    6893                 :            :         rte_spinlock_unlock(&cmng->pool_update_sl);
    6894                 :          0 :         return pool;
    6895                 :            : }
    6896                 :            : 
    6897                 :            : /**
    6898                 :            :  * Prepare a new counter and/or a new counter pool.
    6899                 :            :  *
    6900                 :            :  * @param[in] dev
    6901                 :            :  *   Pointer to the Ethernet device structure.
    6902                 :            :  * @param[out] cnt_free
    6903                 :            :  *   Where to put the pointer of a new counter.
    6904                 :            :  * @param[in] age
    6905                 :            :  *   Whether the pool is for counter that was allocated for aging.
    6906                 :            :  *
    6907                 :            :  * @return
    6908                 :            :  *   The counter pool pointer and @p cnt_free is set on success,
    6909                 :            :  *   NULL otherwise and rte_errno is set.
    6910                 :            :  */
    6911                 :            : static struct mlx5_flow_counter_pool *
    6912                 :          0 : flow_dv_counter_pool_prepare(struct rte_eth_dev *dev,
    6913                 :            :                              struct mlx5_flow_counter **cnt_free,
    6914                 :            :                              uint32_t age)
    6915                 :            : {
    6916                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6917                 :          0 :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6918                 :            :         struct mlx5_flow_counter_pool *pool;
    6919                 :            :         struct mlx5_counters tmp_tq;
    6920                 :            :         struct mlx5_devx_obj *dcs = NULL;
    6921                 :            :         struct mlx5_flow_counter *cnt;
    6922                 :          0 :         enum mlx5_counter_type cnt_type =
    6923                 :          0 :                         age ? MLX5_COUNTER_TYPE_AGE : MLX5_COUNTER_TYPE_ORIGIN;
    6924                 :          0 :         bool fallback = priv->sh->sws_cmng.counter_fallback;
    6925                 :            :         uint32_t i;
    6926                 :            : 
    6927         [ #  # ]:          0 :         if (fallback) {
    6928                 :            :                 /* bulk_bitmap must be 0 for single counter allocation. */
    6929                 :          0 :                 dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0);
    6930         [ #  # ]:          0 :                 if (!dcs)
    6931                 :            :                         return NULL;
    6932                 :          0 :                 pool = flow_dv_find_pool_by_id(cmng, dcs->id);
    6933         [ #  # ]:          0 :                 if (!pool) {
    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                 :            :                 }
    6940                 :          0 :                 i = dcs->id % MLX5_COUNTERS_PER_POOL;
    6941         [ #  # ]:          0 :                 cnt = MLX5_POOL_GET_CNT(pool, i);
    6942                 :          0 :                 cnt->pool = pool;
    6943                 :          0 :                 cnt->dcs_when_free = dcs;
    6944                 :          0 :                 *cnt_free = cnt;
    6945                 :          0 :                 return pool;
    6946                 :            :         }
    6947                 :          0 :         dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0x4);
    6948         [ #  # ]:          0 :         if (!dcs) {
    6949                 :          0 :                 rte_errno = ENODATA;
    6950                 :          0 :                 return NULL;
    6951                 :            :         }
    6952                 :          0 :         pool = flow_dv_pool_create(dev, dcs, age);
    6953         [ #  # ]:          0 :         if (!pool) {
    6954                 :          0 :                 mlx5_devx_cmd_destroy(dcs);
    6955                 :          0 :                 return NULL;
    6956                 :            :         }
    6957                 :          0 :         TAILQ_INIT(&tmp_tq);
    6958         [ #  # ]:          0 :         for (i = 1; i < MLX5_COUNTERS_PER_POOL; ++i) {
    6959         [ #  # ]:          0 :                 cnt = MLX5_POOL_GET_CNT(pool, i);
    6960                 :          0 :                 cnt->pool = pool;
    6961         [ #  # ]:          0 :                 TAILQ_INSERT_HEAD(&tmp_tq, cnt, next);
    6962                 :            :         }
    6963                 :          0 :         rte_spinlock_lock(&cmng->csl[cnt_type]);
    6964         [ #  # ]:          0 :         TAILQ_CONCAT(&cmng->counters[cnt_type], &tmp_tq, next);
    6965                 :            :         rte_spinlock_unlock(&cmng->csl[cnt_type]);
    6966                 :          0 :         *cnt_free = MLX5_POOL_GET_CNT(pool, 0);
    6967                 :          0 :         (*cnt_free)->pool = pool;
    6968                 :          0 :         return pool;
    6969                 :            : }
    6970                 :            : 
    6971                 :            : /**
    6972                 :            :  * Allocate a flow counter.
    6973                 :            :  *
    6974                 :            :  * @param[in] dev
    6975                 :            :  *   Pointer to the Ethernet device structure.
    6976                 :            :  * @param[in] age
    6977                 :            :  *   Whether the counter was allocated for aging.
    6978                 :            :  *
    6979                 :            :  * @return
    6980                 :            :  *   Index to flow counter on success, 0 otherwise and rte_errno is set.
    6981                 :            :  */
    6982                 :            : static uint32_t
    6983                 :          0 : flow_dv_counter_alloc(struct rte_eth_dev *dev, uint32_t age)
    6984                 :            : {
    6985                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    6986                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    6987                 :          0 :         struct mlx5_flow_counter *cnt_free = NULL;
    6988                 :          0 :         bool fallback = priv->sh->sws_cmng.counter_fallback;
    6989                 :            :         struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng;
    6990                 :          0 :         enum mlx5_counter_type cnt_type =
    6991                 :          0 :                         age ? MLX5_COUNTER_TYPE_AGE : MLX5_COUNTER_TYPE_ORIGIN;
    6992                 :            :         uint32_t cnt_idx;
    6993                 :            : 
    6994         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
    6995                 :          0 :                 rte_errno = ENOTSUP;
    6996                 :          0 :                 return 0;
    6997                 :            :         }
    6998                 :            :         /* Get free counters from container. */
    6999                 :          0 :         rte_spinlock_lock(&cmng->csl[cnt_type]);
    7000                 :          0 :         cnt_free = TAILQ_FIRST(&cmng->counters[cnt_type]);
    7001         [ #  # ]:          0 :         if (cnt_free)
    7002         [ #  # ]:          0 :                 TAILQ_REMOVE(&cmng->counters[cnt_type], cnt_free, next);
    7003                 :            :         rte_spinlock_unlock(&cmng->csl[cnt_type]);
    7004   [ #  #  #  # ]:          0 :         if (!cnt_free && !flow_dv_counter_pool_prepare(dev, &cnt_free, age))
    7005                 :          0 :                 goto err;
    7006                 :          0 :         pool = cnt_free->pool;
    7007         [ #  # ]:          0 :         if (fallback)
    7008                 :          0 :                 cnt_free->dcs_when_active = cnt_free->dcs_when_free;
    7009                 :            :         /* Create a DV counter action only in the first time usage. */
    7010         [ #  # ]:          0 :         if (!cnt_free->action) {
    7011                 :            :                 uint16_t offset;
    7012                 :            :                 struct mlx5_devx_obj *dcs;
    7013                 :            :                 int ret;
    7014                 :            : 
    7015         [ #  # ]:          0 :                 if (!fallback) {
    7016         [ #  # ]:          0 :                         offset = MLX5_CNT_ARRAY_IDX(pool, cnt_free);
    7017                 :          0 :                         dcs = pool->min_dcs;
    7018                 :            :                 } else {
    7019                 :            :                         offset = 0;
    7020                 :          0 :                         dcs = cnt_free->dcs_when_free;
    7021                 :            :                 }
    7022                 :          0 :                 ret = mlx5_flow_os_create_flow_action_count(dcs->obj, offset,
    7023                 :            :                                                             &cnt_free->action);
    7024                 :            :                 if (ret) {
    7025                 :          0 :                         rte_errno = errno;
    7026                 :          0 :                         goto err;
    7027                 :            :                 }
    7028                 :            :         }
    7029         [ #  # ]:          0 :         cnt_idx = MLX5_MAKE_CNT_IDX(pool->index,
    7030                 :            :                                 MLX5_CNT_ARRAY_IDX(pool, cnt_free));
    7031                 :            :         /* Update the counter reset values. */
    7032         [ #  # ]:          0 :         if (_flow_dv_query_count(dev, cnt_idx, &cnt_free->hits,
    7033                 :            :                                  &cnt_free->bytes))
    7034                 :          0 :                 goto err;
    7035   [ #  #  #  # ]:          0 :         if (!fallback && !priv->sh->sws_cmng.query_thread_on)
    7036                 :            :                 /* Start the asynchronous batch query by the host thread. */
    7037                 :          0 :                 mlx5_set_query_alarm(priv->sh);
    7038                 :            :         /*
    7039                 :            :          * When the count action isn't shared (by ID), shared_info field is
    7040                 :            :          * used for indirect action API's refcnt.
    7041                 :            :          * When the counter action is not shared neither by ID nor by indirect
    7042                 :            :          * action API, shared info must be 1.
    7043                 :            :          */
    7044                 :          0 :         cnt_free->shared_info.refcnt = 1;
    7045                 :          0 :         return cnt_idx;
    7046                 :          0 : err:
    7047         [ #  # ]:          0 :         if (cnt_free) {
    7048                 :          0 :                 cnt_free->pool = pool;
    7049         [ #  # ]:          0 :                 if (fallback)
    7050                 :          0 :                         cnt_free->dcs_when_free = cnt_free->dcs_when_active;
    7051                 :            :                 rte_spinlock_lock(&cmng->csl[cnt_type]);
    7052                 :          0 :                 TAILQ_INSERT_TAIL(&cmng->counters[cnt_type], cnt_free, next);
    7053                 :            :                 rte_spinlock_unlock(&cmng->csl[cnt_type]);
    7054                 :            :         }
    7055                 :            :         return 0;
    7056                 :            : }
    7057                 :            : 
    7058                 :            : /**
    7059                 :            :  * Get age param from counter index.
    7060                 :            :  *
    7061                 :            :  * @param[in] dev
    7062                 :            :  *   Pointer to the Ethernet device structure.
    7063                 :            :  * @param[in] counter
    7064                 :            :  *   Index to the counter handler.
    7065                 :            :  *
    7066                 :            :  * @return
    7067                 :            :  *   The aging parameter specified for the counter index.
    7068                 :            :  */
    7069                 :            : static struct mlx5_age_param*
    7070                 :            : flow_dv_counter_idx_get_age(struct rte_eth_dev *dev,
    7071                 :            :                                 uint32_t counter)
    7072                 :            : {
    7073                 :            :         struct mlx5_flow_counter *cnt;
    7074                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    7075                 :            : 
    7076                 :            :         flow_dv_counter_get_by_idx(dev, counter, &pool);
    7077                 :            :         counter = (counter - 1) % MLX5_COUNTERS_PER_POOL;
    7078                 :            :         cnt = MLX5_POOL_GET_CNT(pool, counter);
    7079                 :          0 :         return MLX5_CNT_TO_AGE(cnt);
    7080                 :            : }
    7081                 :            : 
    7082                 :            : /**
    7083                 :            :  * Remove a flow counter from aged counter list.
    7084                 :            :  *
    7085                 :            :  * @param[in] dev
    7086                 :            :  *   Pointer to the Ethernet device structure.
    7087                 :            :  * @param[in] counter
    7088                 :            :  *   Index to the counter handler.
    7089                 :            :  * @param[in] cnt
    7090                 :            :  *   Pointer to the counter handler.
    7091                 :            :  */
    7092                 :            : static void
    7093                 :          0 : flow_dv_counter_remove_from_age(struct rte_eth_dev *dev,
    7094                 :            :                                 uint32_t counter, struct mlx5_flow_counter *cnt)
    7095                 :            : {
    7096                 :            :         struct mlx5_age_info *age_info;
    7097                 :            :         struct mlx5_age_param *age_param;
    7098                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7099                 :            :         uint16_t expected = AGE_CANDIDATE;
    7100                 :            : 
    7101         [ #  # ]:          0 :         age_info = GET_PORT_AGE_INFO(priv);
    7102                 :            :         age_param = flow_dv_counter_idx_get_age(dev, counter);
    7103         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&age_param->state, &expected,
    7104                 :            :                                          AGE_FREE, rte_memory_order_relaxed,
    7105                 :            :                                          rte_memory_order_relaxed)) {
    7106                 :            :                 /**
    7107                 :            :                  * We need the lock even it is age timeout,
    7108                 :            :                  * since counter may still in process.
    7109                 :            :                  */
    7110                 :          0 :                 rte_spinlock_lock(&age_info->aged_sl);
    7111         [ #  # ]:          0 :                 TAILQ_REMOVE(&age_info->aged_counters, cnt, next);
    7112                 :            :                 rte_spinlock_unlock(&age_info->aged_sl);
    7113                 :          0 :                 rte_atomic_store_explicit(&age_param->state, AGE_FREE, rte_memory_order_relaxed);
    7114                 :            :         }
    7115                 :          0 : }
    7116                 :            : 
    7117                 :            : /**
    7118                 :            :  * Release a flow counter.
    7119                 :            :  *
    7120                 :            :  * @param[in] dev
    7121                 :            :  *   Pointer to the Ethernet device structure.
    7122                 :            :  * @param[in] counter
    7123                 :            :  *   Index to the counter handler.
    7124                 :            :  */
    7125                 :            : static void
    7126                 :          0 : flow_dv_counter_free(struct rte_eth_dev *dev, uint32_t counter)
    7127                 :            : {
    7128                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7129                 :            :         struct mlx5_flow_counter_pool *pool = NULL;
    7130                 :            :         struct mlx5_flow_counter *cnt;
    7131                 :            :         enum mlx5_counter_type cnt_type;
    7132                 :            : 
    7133         [ #  # ]:          0 :         if (!counter)
    7134                 :            :                 return;
    7135                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, &pool);
    7136                 :            :         MLX5_ASSERT(pool);
    7137         [ #  # ]:          0 :         if (pool->is_aged) {
    7138                 :          0 :                 flow_dv_counter_remove_from_age(dev, counter, cnt);
    7139                 :            :         } else {
    7140                 :            :                 /*
    7141                 :            :                  * If the counter action is shared by indirect action API,
    7142                 :            :                  * the atomic function reduces its references counter.
    7143                 :            :                  * If after the reduction the action is still referenced, the
    7144                 :            :                  * function returns here and does not release it.
    7145                 :            :                  * When the counter action is not shared by
    7146                 :            :                  * indirect action API, shared info is 1 before the reduction,
    7147                 :            :                  * so this condition is failed and function doesn't return here.
    7148                 :            :                  */
    7149         [ #  # ]:          0 :                 if (rte_atomic_fetch_sub_explicit(&cnt->shared_info.refcnt, 1,
    7150                 :            :                                        rte_memory_order_relaxed) - 1)
    7151                 :            :                         return;
    7152                 :            :         }
    7153                 :          0 :         cnt->pool = pool;
    7154                 :            :         /*
    7155                 :            :          * Put the counter back to list to be updated in none fallback mode.
    7156                 :            :          * Currently, we are using two list alternately, while one is in query,
    7157                 :            :          * add the freed counter to the other list based on the pool query_gen
    7158                 :            :          * value. After query finishes, add counter the list to the global
    7159                 :            :          * container counter list. The list changes while query starts. In
    7160                 :            :          * this case, lock will not be needed as query callback and release
    7161                 :            :          * function both operate with the different list.
    7162                 :            :          */
    7163         [ #  # ]:          0 :         if (!priv->sh->sws_cmng.counter_fallback) {
    7164                 :          0 :                 rte_spinlock_lock(&pool->csl);
    7165                 :          0 :                 TAILQ_INSERT_TAIL(&pool->counters[pool->query_gen], cnt, next);
    7166                 :            :                 rte_spinlock_unlock(&pool->csl);
    7167                 :            :         } else {
    7168                 :          0 :                 cnt->dcs_when_free = cnt->dcs_when_active;
    7169                 :          0 :                 cnt_type = pool->is_aged ? MLX5_COUNTER_TYPE_AGE :
    7170                 :            :                                            MLX5_COUNTER_TYPE_ORIGIN;
    7171                 :          0 :                 rte_spinlock_lock(&priv->sh->sws_cmng.csl[cnt_type]);
    7172                 :          0 :                 TAILQ_INSERT_TAIL(&priv->sh->sws_cmng.counters[cnt_type],
    7173                 :            :                                   cnt, next);
    7174                 :          0 :                 rte_spinlock_unlock(&priv->sh->sws_cmng.csl[cnt_type]);
    7175                 :            :         }
    7176                 :            : }
    7177                 :            : 
    7178                 :            : /**
    7179                 :            :  * Resize a meter id container.
    7180                 :            :  *
    7181                 :            :  * @param[in] dev
    7182                 :            :  *   Pointer to the Ethernet device structure.
    7183                 :            :  *
    7184                 :            :  * @return
    7185                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
    7186                 :            :  */
    7187                 :            : static int
    7188                 :          0 : flow_dv_mtr_container_resize(struct rte_eth_dev *dev)
    7189                 :            : {
    7190                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7191                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7192                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7193                 :          0 :         void *old_pools = pools_mng->pools;
    7194                 :          0 :         uint32_t resize = pools_mng->n + MLX5_MTRS_CONTAINER_RESIZE;
    7195                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_mtr_pool *) * resize;
    7196                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
    7197                 :            : 
    7198         [ #  # ]:          0 :         if (!pools) {
    7199                 :          0 :                 rte_errno = ENOMEM;
    7200                 :          0 :                 return -ENOMEM;
    7201                 :            :         }
    7202         [ #  # ]:          0 :         if (!pools_mng->n)
    7203         [ #  # ]:          0 :                 if (mlx5_aso_queue_init(priv->sh, ASO_OPC_MOD_POLICER, 1)) {
    7204                 :          0 :                         mlx5_free(pools);
    7205                 :          0 :                         return -ENOMEM;
    7206                 :            :                 }
    7207         [ #  # ]:          0 :         if (old_pools)
    7208                 :          0 :                 memcpy(pools, old_pools, pools_mng->n *
    7209                 :            :                                        sizeof(struct mlx5_aso_mtr_pool *));
    7210                 :          0 :         pools_mng->n = resize;
    7211                 :          0 :         pools_mng->pools = pools;
    7212         [ #  # ]:          0 :         if (old_pools)
    7213                 :          0 :                 mlx5_free(old_pools);
    7214                 :            :         return 0;
    7215                 :            : }
    7216                 :            : 
    7217                 :            : /**
    7218                 :            :  * Prepare a new meter and/or a new meter pool.
    7219                 :            :  *
    7220                 :            :  * @param[in] dev
    7221                 :            :  *   Pointer to the Ethernet device structure.
    7222                 :            :  * @param[out] mtr_free
    7223                 :            :  *   Where to put the pointer of a new meter.g.
    7224                 :            :  *
    7225                 :            :  * @return
    7226                 :            :  *   The meter pool pointer and @mtr_free is set on success,
    7227                 :            :  *   NULL otherwise and rte_errno is set.
    7228                 :            :  */
    7229                 :            : static struct mlx5_aso_mtr_pool *
    7230                 :          0 : flow_dv_mtr_pool_create(struct rte_eth_dev *dev, struct mlx5_aso_mtr **mtr_free)
    7231                 :            : {
    7232                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7233                 :          0 :         struct mlx5_aso_mtr_pools_mng *pools_mng = &priv->sh->mtrmng->pools_mng;
    7234                 :            :         struct mlx5_aso_mtr_pool *pool = NULL;
    7235                 :            :         struct mlx5_devx_obj *dcs = NULL;
    7236                 :            :         uint32_t i;
    7237                 :            :         uint32_t log_obj_size;
    7238                 :            : 
    7239                 :            :         log_obj_size = rte_log2_u32(MLX5_ASO_MTRS_PER_POOL >> 1);
    7240                 :          0 :         dcs = mlx5_devx_cmd_create_flow_meter_aso_obj(priv->sh->cdev->ctx,
    7241                 :          0 :                                                       priv->sh->cdev->pdn,
    7242                 :            :                                                       log_obj_size);
    7243         [ #  # ]:          0 :         if (!dcs) {
    7244                 :          0 :                 rte_errno = ENODATA;
    7245                 :          0 :                 return NULL;
    7246                 :            :         }
    7247                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY);
    7248         [ #  # ]:          0 :         if (!pool) {
    7249                 :          0 :                 rte_errno = ENOMEM;
    7250                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
    7251                 :          0 :                 return NULL;
    7252                 :            :         }
    7253                 :          0 :         pool->devx_obj = dcs;
    7254                 :          0 :         rte_rwlock_write_lock(&pools_mng->resize_mtrwl);
    7255                 :          0 :         pool->index = pools_mng->n_valid;
    7256   [ #  #  #  # ]:          0 :         if (pool->index == pools_mng->n && flow_dv_mtr_container_resize(dev)) {
    7257                 :          0 :                 mlx5_free(pool);
    7258                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
    7259                 :            :                 rte_rwlock_write_unlock(&pools_mng->resize_mtrwl);
    7260                 :          0 :                 return NULL;
    7261                 :            :         }
    7262                 :          0 :         pools_mng->pools[pool->index] = pool;
    7263                 :          0 :         pools_mng->n_valid++;
    7264                 :            :         rte_rwlock_write_unlock(&pools_mng->resize_mtrwl);
    7265         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_MTRS_PER_POOL; ++i) {
    7266                 :          0 :                 pool->mtrs[i].offset = i;
    7267         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&pools_mng->meters, &pool->mtrs[i], next);
    7268                 :            :         }
    7269                 :          0 :         pool->mtrs[0].offset = 0;
    7270                 :          0 :         *mtr_free = &pool->mtrs[0];
    7271                 :          0 :         return pool;
    7272                 :            : }
    7273                 :            : 
    7274                 :            : /**
    7275                 :            :  * Release a flow meter into pool.
    7276                 :            :  *
    7277                 :            :  * @param[in] dev
    7278                 :            :  *   Pointer to the Ethernet device structure.
    7279                 :            :  * @param[in] mtr_idx
    7280                 :            :  *   Index to aso flow meter.
    7281                 :            :  */
    7282                 :            : static void
    7283                 :          0 : flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)
    7284                 :            : {
    7285                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7286                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7287                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7288                 :          0 :         struct mlx5_aso_mtr *aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
    7289                 :            :         void *meter_action_g;
    7290                 :            :         void *meter_action_y;
    7291                 :            : 
    7292                 :            :         MLX5_ASSERT(aso_mtr);
    7293                 :          0 :         rte_spinlock_lock(&pools_mng->mtrsl);
    7294                 :          0 :         meter_action_g = aso_mtr->fm.meter_action_g;
    7295                 :          0 :         meter_action_y = aso_mtr->fm.meter_action_y;
    7296         [ #  # ]:          0 :         memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
    7297                 :          0 :         aso_mtr->fm.meter_action_g = meter_action_g;
    7298                 :          0 :         aso_mtr->fm.meter_action_y = meter_action_y;
    7299                 :          0 :         aso_mtr->state = ASO_METER_FREE;
    7300         [ #  # ]:          0 :         LIST_INSERT_HEAD(&pools_mng->meters, aso_mtr, next);
    7301                 :            :         rte_spinlock_unlock(&pools_mng->mtrsl);
    7302                 :          0 : }
    7303                 :            : 
    7304                 :            : /**
    7305                 :            :  * Allocate a aso flow meter.
    7306                 :            :  *
    7307                 :            :  * @param[in] dev
    7308                 :            :  *   Pointer to the Ethernet device structure.
    7309                 :            :  *
    7310                 :            :  * @return
    7311                 :            :  *   Index to aso flow meter on success, 0 otherwise and rte_errno is set.
    7312                 :            :  */
    7313                 :            : static uint32_t
    7314                 :          0 : flow_dv_mtr_alloc(struct rte_eth_dev *dev)
    7315                 :            : {
    7316                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7317                 :          0 :         struct mlx5_aso_mtr *mtr_free = NULL;
    7318                 :            :         struct mlx5_aso_mtr_pools_mng *pools_mng =
    7319                 :          0 :                                 &priv->sh->mtrmng->pools_mng;
    7320                 :            :         struct mlx5_aso_mtr_pool *pool;
    7321                 :            :         uint32_t mtr_idx = 0;
    7322                 :            : 
    7323         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
    7324                 :          0 :                 rte_errno = ENOTSUP;
    7325                 :          0 :                 return 0;
    7326                 :            :         }
    7327                 :            :         /* Allocate the flow meter memory. */
    7328                 :            :         /* Get free meters from management. */
    7329                 :          0 :         rte_spinlock_lock(&pools_mng->mtrsl);
    7330                 :          0 :         mtr_free = LIST_FIRST(&pools_mng->meters);
    7331         [ #  # ]:          0 :         if (mtr_free)
    7332         [ #  # ]:          0 :                 LIST_REMOVE(mtr_free, next);
    7333   [ #  #  #  # ]:          0 :         if (!mtr_free && !flow_dv_mtr_pool_create(dev, &mtr_free)) {
    7334                 :            :                 rte_spinlock_unlock(&pools_mng->mtrsl);
    7335                 :          0 :                 return 0;
    7336                 :            :         }
    7337                 :          0 :         mtr_free->state = ASO_METER_WAIT;
    7338                 :            :         rte_spinlock_unlock(&pools_mng->mtrsl);
    7339                 :          0 :         pool = container_of(mtr_free,
    7340                 :            :                         struct mlx5_aso_mtr_pool,
    7341                 :            :                         mtrs[mtr_free->offset]);
    7342                 :          0 :         mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);
    7343         [ #  # ]:          0 :         if (!mtr_free->fm.meter_action_g) {
    7344                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
    7345                 :            :                 struct rte_flow_error error;
    7346                 :            :                 uint8_t reg_id;
    7347                 :            : 
    7348                 :          0 :                 reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &error);
    7349                 :          0 :                 mtr_free->fm.meter_action_g =
    7350                 :          0 :                         mlx5_glue->dv_create_flow_action_aso
    7351                 :          0 :                                                 (priv->sh->rx_domain,
    7352                 :          0 :                                                  pool->devx_obj->obj,
    7353                 :            :                                                  mtr_free->offset,
    7354                 :            :                                                  (1 << MLX5_FLOW_COLOR_GREEN),
    7355                 :          0 :                                                  reg_id - REG_C_0);
    7356                 :            : #endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
    7357         [ #  # ]:          0 :                 if (!mtr_free->fm.meter_action_g) {
    7358                 :          0 :                         flow_dv_aso_mtr_release_to_pool(dev, mtr_idx);
    7359                 :          0 :                         return 0;
    7360                 :            :                 }
    7361                 :            :         }
    7362                 :            :         return mtr_idx;
    7363                 :            : }
    7364                 :            : 
    7365                 :            : /**
    7366                 :            :  * Verify the @p attributes will be correctly understood by the NIC and store
    7367                 :            :  * them in the @p flow if everything is correct.
    7368                 :            :  *
    7369                 :            :  * @param[in] dev
    7370                 :            :  *   Pointer to dev struct.
    7371                 :            :  * @param[in] attributes
    7372                 :            :  *   Pointer to flow attributes
    7373                 :            :  * @param[in] external
    7374                 :            :  *   This flow rule is created by request external to PMD.
    7375                 :            :  * @param[out] error
    7376                 :            :  *   Pointer to error structure.
    7377                 :            :  *
    7378                 :            :  * @return
    7379                 :            :  *   - 0 on success and non root table.
    7380                 :            :  *   - 1 on success and root table.
    7381                 :            :  *   - a negative errno value otherwise and rte_errno is set.
    7382                 :            :  */
    7383                 :            : static int
    7384                 :          0 : flow_dv_validate_attributes(struct rte_eth_dev *dev,
    7385                 :            :                             const struct mlx5_flow_tunnel *tunnel,
    7386                 :            :                             const struct rte_flow_attr *attributes,
    7387                 :            :                             const struct flow_grp_info *grp_info,
    7388                 :            :                             struct rte_flow_error *error)
    7389                 :            : {
    7390                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7391                 :          0 :         uint32_t lowest_priority = mlx5_get_lowest_priority(dev, attributes);
    7392                 :            :         int ret = 0;
    7393                 :            : 
    7394                 :            : #ifndef HAVE_MLX5DV_DR
    7395                 :            :         RTE_SET_USED(tunnel);
    7396                 :            :         RTE_SET_USED(grp_info);
    7397                 :            :         if (attributes->group)
    7398                 :            :                 return rte_flow_error_set(error, ENOTSUP,
    7399                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
    7400                 :            :                                           NULL,
    7401                 :            :                                           "groups are not supported");
    7402                 :            : #else
    7403                 :          0 :         uint32_t table = 0;
    7404                 :            : 
    7405                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, attributes->group, &table,
    7406                 :            :                                        grp_info, error);
    7407         [ #  # ]:          0 :         if (ret)
    7408                 :            :                 return ret;
    7409         [ #  # ]:          0 :         if (!table)
    7410                 :            :                 ret = MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL;
    7411                 :            : #endif
    7412   [ #  #  #  # ]:          0 :         if (attributes->priority != MLX5_FLOW_LOWEST_PRIO_INDICATOR &&
    7413                 :            :             attributes->priority > lowest_priority)
    7414                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7415                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
    7416                 :            :                                           NULL,
    7417                 :            :                                           "priority out of range");
    7418   [ #  #  #  # ]:          0 :         if (attributes->transfer && !priv->sh->config.dv_esw_en)
    7419                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7420                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    7421                 :            :                                           "E-Switch dr is not supported");
    7422         [ #  # ]:          0 :         if (attributes->ingress + attributes->egress + attributes->transfer != 1) {
    7423                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7424                 :            :                                           RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    7425                 :            :                                           "must specify exactly one of "
    7426                 :            :                                           "ingress, egress or transfer");
    7427                 :            :         }
    7428                 :            :         return ret;
    7429                 :            : }
    7430                 :            : 
    7431                 :            : static int
    7432                 :          0 : validate_integrity_bits(const void *arg,
    7433                 :            :                         int64_t pattern_flags, uint64_t l3_flags,
    7434                 :            :                         uint64_t l4_flags, uint64_t ip4_flag,
    7435                 :            :                         struct rte_flow_error *error)
    7436                 :            : {
    7437                 :            :         const struct rte_flow_item_integrity *mask = arg;
    7438                 :            : 
    7439   [ #  #  #  # ]:          0 :         if (mask->l3_ok && !(pattern_flags & l3_flags))
    7440                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7441                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7442                 :            :                                           NULL, "missing L3 protocol");
    7443                 :            : 
    7444   [ #  #  #  # ]:          0 :         if (mask->ipv4_csum_ok && !(pattern_flags & ip4_flag))
    7445                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7446                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7447                 :            :                                           NULL, "missing IPv4 protocol");
    7448                 :            : 
    7449   [ #  #  #  # ]:          0 :         if ((mask->l4_ok || mask->l4_csum_ok) && !(pattern_flags & l4_flags))
    7450                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7451                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7452                 :            :                                           NULL, "missing L4 protocol");
    7453                 :            : 
    7454                 :            :         return 0;
    7455                 :            : }
    7456                 :            : 
    7457                 :            : static int
    7458                 :          0 : flow_dv_validate_item_integrity_post(const struct
    7459                 :            :                                      rte_flow_item *integrity_items[2],
    7460                 :            :                                      int64_t pattern_flags,
    7461                 :            :                                      struct rte_flow_error *error)
    7462                 :            : {
    7463                 :            :         const struct rte_flow_item_integrity *mask;
    7464                 :            :         int ret;
    7465                 :            : 
    7466         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY) {
    7467                 :          0 :                 mask = (typeof(mask))integrity_items[0]->mask;
    7468                 :          0 :                 ret = validate_integrity_bits(mask, pattern_flags,
    7469                 :            :                                               MLX5_FLOW_LAYER_OUTER_L3,
    7470                 :            :                                               MLX5_FLOW_LAYER_OUTER_L4,
    7471                 :            :                                               MLX5_FLOW_LAYER_OUTER_L3_IPV4,
    7472                 :            :                                               error);
    7473         [ #  # ]:          0 :                 if (ret)
    7474                 :            :                         return ret;
    7475                 :            :         }
    7476         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY) {
    7477                 :          0 :                 mask = (typeof(mask))integrity_items[1]->mask;
    7478                 :          0 :                 ret = validate_integrity_bits(mask, pattern_flags,
    7479                 :            :                                               MLX5_FLOW_LAYER_INNER_L3,
    7480                 :            :                                               MLX5_FLOW_LAYER_INNER_L4,
    7481                 :            :                                               MLX5_FLOW_LAYER_INNER_L3_IPV4,
    7482                 :            :                                               error);
    7483         [ #  # ]:          0 :                 if (ret)
    7484                 :          0 :                         return ret;
    7485                 :            :         }
    7486                 :            :         return 0;
    7487                 :            : }
    7488                 :            : 
    7489                 :            : static int
    7490                 :          0 : flow_dv_validate_item_integrity(struct rte_eth_dev *dev,
    7491                 :            :                                 const struct rte_flow_item *integrity_item,
    7492                 :            :                                 uint64_t pattern_flags, uint64_t *last_item,
    7493                 :            :                                 const struct rte_flow_item *integrity_items[2],
    7494                 :            :                                 struct rte_flow_error *error)
    7495                 :            : {
    7496                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7497                 :          0 :         const struct rte_flow_item_integrity *mask = (typeof(mask))
    7498                 :            :                                                      integrity_item->mask;
    7499                 :          0 :         const struct rte_flow_item_integrity *spec = (typeof(spec))
    7500                 :            :                                                      integrity_item->spec;
    7501                 :            : 
    7502         [ #  # ]:          0 :         if (!priv->sh->cdev->config.hca_attr.pkt_integrity_match)
    7503                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7504                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7505                 :            :                                           integrity_item,
    7506                 :            :                                           "packet integrity integrity_item not supported");
    7507         [ #  # ]:          0 :         if (!spec)
    7508                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7509                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7510                 :            :                                           integrity_item,
    7511                 :            :                                           "no spec for integrity item");
    7512         [ #  # ]:          0 :         if (!mask)
    7513                 :            :                 mask = &rte_flow_item_integrity_mask;
    7514         [ #  # ]:          0 :         if (!mlx5_validate_integrity_item(mask))
    7515                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7516                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7517                 :            :                                           integrity_item,
    7518                 :            :                                           "unsupported integrity filter");
    7519   [ #  #  #  # ]:          0 :         if ((mask->l3_ok & !spec->l3_ok) || (mask->l4_ok & !spec->l4_ok) ||
    7520         [ #  # ]:          0 :                 (mask->ipv4_csum_ok & !spec->ipv4_csum_ok) ||
    7521         [ #  # ]:          0 :                 (mask->l4_csum_ok & !spec->l4_csum_ok))
    7522                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7523                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7524                 :            :                                           NULL, "negative integrity flow is not supported");
    7525         [ #  # ]:          0 :         if (spec->level > 1) {
    7526         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY)
    7527                 :          0 :                         return rte_flow_error_set
    7528                 :            :                                 (error, ENOTSUP,
    7529                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM,
    7530                 :            :                                  NULL, "multiple inner integrity items not supported");
    7531                 :          0 :                 integrity_items[1] = integrity_item;
    7532                 :          0 :                 *last_item |= MLX5_FLOW_ITEM_INNER_INTEGRITY;
    7533                 :            :         } else {
    7534         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY)
    7535                 :          0 :                         return rte_flow_error_set
    7536                 :            :                                 (error, ENOTSUP,
    7537                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM,
    7538                 :            :                                  NULL, "multiple outer integrity items not supported");
    7539                 :          0 :                 integrity_items[0] = integrity_item;
    7540                 :          0 :                 *last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
    7541                 :            :         }
    7542                 :            :         return 0;
    7543                 :            : }
    7544                 :            : 
    7545                 :            : static int
    7546                 :          0 : flow_dv_validate_item_flex(struct rte_eth_dev *dev,
    7547                 :            :                            const struct rte_flow_item *item,
    7548                 :            :                            uint64_t item_flags,
    7549                 :            :                            uint64_t *last_item,
    7550                 :            :                            bool is_inner,
    7551                 :            :                            struct rte_flow_error *error)
    7552                 :            : {
    7553                 :          0 :         const struct rte_flow_item_flex *flow_spec = item->spec;
    7554                 :          0 :         const struct rte_flow_item_flex *flow_mask = item->mask;
    7555                 :            :         struct mlx5_flex_item *flex;
    7556                 :            : 
    7557         [ #  # ]:          0 :         if (!flow_spec)
    7558                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7559                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7560                 :            :                                           "flex flow item spec cannot be NULL");
    7561         [ #  # ]:          0 :         if (!flow_mask)
    7562                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7563                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7564                 :            :                                           "flex flow item mask cannot be NULL");
    7565         [ #  # ]:          0 :         if (item->last)
    7566                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    7567                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7568                 :            :                                           "flex flow item last not supported");
    7569         [ #  # ]:          0 :         if (mlx5_flex_acquire_index(dev, flow_spec->handle, false) < 0)
    7570                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7571                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    7572                 :            :                                           "invalid flex flow item handle");
    7573                 :          0 :         flex = (struct mlx5_flex_item *)flow_spec->handle;
    7574   [ #  #  #  #  :          0 :         switch (flex->tunnel_mode) {
                   #  # ]
    7575                 :          0 :         case FLEX_TUNNEL_MODE_SINGLE:
    7576         [ #  # ]:          0 :                 if (item_flags &
    7577                 :            :                     (MLX5_FLOW_ITEM_OUTER_FLEX | MLX5_FLOW_ITEM_INNER_FLEX))
    7578                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7579                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7580                 :            :                                            NULL, "multiple flex items not supported");
    7581                 :            :                 break;
    7582                 :          0 :         case FLEX_TUNNEL_MODE_OUTER:
    7583         [ #  # ]:          0 :                 if (is_inner)
    7584                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7585                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7586                 :            :                                            NULL, "inner flex item was not configured");
    7587         [ #  # ]:          0 :                 if (item_flags & MLX5_FLOW_ITEM_OUTER_FLEX)
    7588                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    7589                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7590                 :            :                                            NULL, "multiple flex items not supported");
    7591                 :            :                 break;
    7592                 :          0 :         case FLEX_TUNNEL_MODE_INNER:
    7593         [ #  # ]:          0 :                 if (!is_inner)
    7594                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7595                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7596                 :            :                                            NULL, "outer flex item was not configured");
    7597         [ #  # ]:          0 :                 if (item_flags & MLX5_FLOW_ITEM_INNER_FLEX)
    7598                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7599                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7600                 :            :                                            NULL, "multiple flex items not supported");
    7601                 :            :                 break;
    7602                 :          0 :         case FLEX_TUNNEL_MODE_MULTI:
    7603   [ #  #  #  #  :          0 :                 if ((is_inner && (item_flags & MLX5_FLOW_ITEM_INNER_FLEX)) ||
                   #  # ]
    7604         [ #  # ]:          0 :                     (!is_inner && (item_flags & MLX5_FLOW_ITEM_OUTER_FLEX))) {
    7605                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7606                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7607                 :            :                                            NULL, "multiple flex items not supported");
    7608                 :            :                 }
    7609                 :            :                 break;
    7610                 :          0 :         case FLEX_TUNNEL_MODE_TUNNEL:
    7611   [ #  #  #  # ]:          0 :                 if (is_inner || (item_flags & MLX5_FLOW_ITEM_FLEX_TUNNEL))
    7612                 :          0 :                         rte_flow_error_set(error, EINVAL,
    7613                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    7614                 :            :                                            NULL, "multiple flex tunnel items not supported");
    7615                 :            :                 break;
    7616                 :          0 :         default:
    7617                 :          0 :                 rte_flow_error_set(error, EINVAL,
    7618                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM,
    7619                 :            :                                    NULL, "invalid flex item configuration");
    7620                 :            :         }
    7621                 :          0 :         *last_item = flex->tunnel_mode == FLEX_TUNNEL_MODE_TUNNEL ?
    7622         [ #  # ]:          0 :                      MLX5_FLOW_ITEM_FLEX_TUNNEL : is_inner ?
    7623         [ #  # ]:          0 :                      MLX5_FLOW_ITEM_INNER_FLEX : MLX5_FLOW_ITEM_OUTER_FLEX;
    7624                 :          0 :         return 0;
    7625                 :            : }
    7626                 :            : 
    7627                 :            : static __rte_always_inline uint8_t
    7628                 :            : mlx5_flow_l3_next_protocol(const struct rte_flow_item *l3_item,
    7629                 :            :                            enum MLX5_SET_MATCHER key_type)
    7630                 :            : {
    7631                 :            : #define MLX5_L3_NEXT_PROTOCOL(i, ms)                                            \
    7632                 :            :         ((i)->type == RTE_FLOW_ITEM_TYPE_IPV4 ?                                  \
    7633                 :            :         ((const struct rte_flow_item_ipv4 *)(i)->ms)->hdr.next_proto_id :       \
    7634                 :            :         (i)->type == RTE_FLOW_ITEM_TYPE_IPV6 ?                                  \
    7635                 :            :         ((const struct rte_flow_item_ipv6 *)(i)->ms)->hdr.proto :               \
    7636                 :            :         (i)->type == RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT ?                         \
    7637                 :            :         ((const struct rte_flow_item_ipv6_frag_ext *)(i)->ms)->hdr.next_header :\
    7638                 :            :         0xff)
    7639                 :            : 
    7640                 :            :         uint8_t next_protocol;
    7641                 :            : 
    7642   [ #  #  #  #  :          0 :         if (l3_item->mask != NULL && l3_item->spec != NULL) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    7643   [ #  #  #  #  :          0 :                 next_protocol = MLX5_L3_NEXT_PROTOCOL(l3_item, mask);
          #  #  #  #  #  
                #  #  # ]
    7644   [ #  #  #  #  :          0 :                 if (next_protocol)
          #  #  #  #  #  
                #  #  # ]
    7645   [ #  #  #  #  :          0 :                         next_protocol &= MLX5_L3_NEXT_PROTOCOL(l3_item, spec);
          #  #  #  #  #  
                #  #  # ]
    7646                 :            :                 else
    7647                 :            :                         next_protocol = 0xff;
    7648   [ #  #  #  #  :          0 :         } else if (key_type == MLX5_SET_MATCHER_HS_M && l3_item->mask != NULL) {
          #  #  #  #  #  
                #  #  # ]
    7649   [ #  #  #  #  :          0 :                 next_protocol =  MLX5_L3_NEXT_PROTOCOL(l3_item, mask);
                   #  # ]
    7650   [ #  #  #  #  :          0 :         } else if (key_type == MLX5_SET_MATCHER_HS_V && l3_item->spec != NULL) {
          #  #  #  #  #  
                #  #  # ]
    7651   [ #  #  #  #  :          0 :                 next_protocol =  MLX5_L3_NEXT_PROTOCOL(l3_item, spec);
                   #  # ]
    7652                 :            :         } else {
    7653                 :            :                 /* Reset for inner layer. */
    7654                 :            :                 next_protocol = 0xff;
    7655                 :            :         }
    7656                 :            :         return next_protocol;
    7657                 :            : 
    7658                 :            : #undef MLX5_L3_NEXT_PROTOCOL
    7659                 :            : }
    7660                 :            : 
    7661                 :            : /**
    7662                 :            :  * Validate IB BTH item.
    7663                 :            :  *
    7664                 :            :  * @param[in] dev
    7665                 :            :  *   Pointer to the rte_eth_dev structure.
    7666                 :            :  * @param[in] udp_dport
    7667                 :            :  *   UDP destination port
    7668                 :            :  * @param[in] item
    7669                 :            :  *   Item specification.
    7670                 :            :  * @param root
    7671                 :            :  *   Whether action is on root table.
    7672                 :            :  * @param[out] error
    7673                 :            :  *   Pointer to the error structure.
    7674                 :            :  *
    7675                 :            :  * @return
    7676                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    7677                 :            :  */
    7678                 :            : static int
    7679                 :          0 : mlx5_flow_validate_item_ib_bth(struct rte_eth_dev *dev,
    7680                 :            :                                uint16_t udp_dport,
    7681                 :            :                                const struct rte_flow_item *item,
    7682                 :            :                                bool root,
    7683                 :            :                                struct rte_flow_error *error)
    7684                 :            : {
    7685                 :          0 :         const struct rte_flow_item_ib_bth *mask = item->mask;
    7686                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7687                 :            :         const struct rte_flow_item_ib_bth *valid_mask;
    7688                 :            :         int ret;
    7689                 :            : 
    7690                 :            :         valid_mask = &rte_flow_item_ib_bth_mask;
    7691         [ #  # ]:          0 :         if (udp_dport && udp_dport != MLX5_UDP_PORT_ROCEv2)
    7692                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7693                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    7694                 :            :                                           "protocol filtering not compatible"
    7695                 :            :                                           " with UDP layer");
    7696   [ #  #  #  # ]:          0 :         if (mask && (mask->hdr.se || mask->hdr.m || mask->hdr.padcnt ||
    7697   [ #  #  #  # ]:          0 :                 mask->hdr.tver || mask->hdr.pkey || mask->hdr.f || mask->hdr.b ||
    7698         [ #  # ]:          0 :                 mask->hdr.rsvd0 || mask->hdr.a || mask->hdr.rsvd1 ||
    7699   [ #  #  #  #  :          0 :                 mask->hdr.psn[0] || mask->hdr.psn[1] || mask->hdr.psn[2]))
                   #  # ]
    7700                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7701                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    7702                 :            :                                           "only opcode and dst_qp are supported");
    7703   [ #  #  #  # ]:          0 :         if (root || priv->sh->steering_format_version ==
    7704                 :            :                 MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5)
    7705                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    7706                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    7707                 :            :                                           item,
    7708                 :            :                                           "IB BTH item is not supported");
    7709         [ #  # ]:          0 :         if (!mask)
    7710                 :            :                 mask = &rte_flow_item_ib_bth_mask;
    7711                 :          0 :         ret = mlx5_flow_item_acceptable(dev, item, (const uint8_t *)mask,
    7712                 :            :                                         (const uint8_t *)valid_mask,
    7713                 :            :                                         sizeof(struct rte_flow_item_ib_bth),
    7714                 :            :                                         MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
    7715                 :            :         if (ret < 0)
    7716                 :            :                 return ret;
    7717                 :            :         return 0;
    7718                 :            : }
    7719                 :            : 
    7720                 :            : const struct rte_flow_item_ipv4 nic_ipv4_mask = {
    7721                 :            :         .hdr = {
    7722                 :            :                 .src_addr = RTE_BE32(0xffffffff),
    7723                 :            :                 .dst_addr = RTE_BE32(0xffffffff),
    7724                 :            :                 .type_of_service = 0xff,
    7725                 :            :                 .fragment_offset = RTE_BE16(0xffff),
    7726                 :            :                 .next_proto_id = 0xff,
    7727                 :            :                 .time_to_live = 0xff,
    7728                 :            :         },
    7729                 :            : };
    7730                 :            : 
    7731                 :            : const struct rte_flow_item_ipv6 nic_ipv6_mask = {
    7732                 :            :         .hdr = {
    7733                 :            :                 .src_addr = RTE_IPV6_MASK_FULL,
    7734                 :            :                 .dst_addr = RTE_IPV6_MASK_FULL,
    7735                 :            :                 .vtc_flow = RTE_BE32(0xffffffff),
    7736                 :            :                 .proto = 0xff,
    7737                 :            :                 .hop_limits = 0xff,
    7738                 :            :         },
    7739                 :            :         .has_frag_ext = 1,
    7740                 :            : };
    7741                 :            : 
    7742                 :            : const struct rte_flow_item_tcp nic_tcp_mask = {
    7743                 :            :         .hdr = {
    7744                 :            :                 .tcp_flags = 0xFF,
    7745                 :            :                 .src_port = RTE_BE16(UINT16_MAX),
    7746                 :            :                 .dst_port = RTE_BE16(UINT16_MAX),
    7747                 :            :         }
    7748                 :            : };
    7749                 :            : 
    7750                 :            : /**
    7751                 :            :  * Internal validation function. For validating both actions and items.
    7752                 :            :  *
    7753                 :            :  * @param[in] dev
    7754                 :            :  *   Pointer to the rte_eth_dev structure.
    7755                 :            :  * @param[in] attr
    7756                 :            :  *   Pointer to the flow attributes.
    7757                 :            :  * @param[in] items
    7758                 :            :  *   Pointer to the list of items.
    7759                 :            :  * @param[in] actions
    7760                 :            :  *   Pointer to the list of actions.
    7761                 :            :  * @param[in] external
    7762                 :            :  *   This flow rule is created by request external to PMD.
    7763                 :            :  * @param[in] hairpin
    7764                 :            :  *   Number of hairpin TX actions, 0 means classic flow.
    7765                 :            :  * @param[out] error
    7766                 :            :  *   Pointer to the error structure.
    7767                 :            :  *
    7768                 :            :  * @return
    7769                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    7770                 :            :  */
    7771                 :            : int
    7772                 :          0 : mlx5_flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
    7773                 :            :                       const struct rte_flow_item items[],
    7774                 :            :                       const struct rte_flow_action actions[],
    7775                 :            :                       bool external, int hairpin, struct rte_flow_error *error)
    7776                 :            : {
    7777                 :            :         int ret;
    7778                 :          0 :         uint64_t aso_mask, action_flags = 0;
    7779                 :          0 :         uint64_t item_flags = 0;
    7780                 :          0 :         uint64_t last_item = 0;
    7781                 :            :         uint8_t next_protocol = 0xff;
    7782                 :            :         uint16_t ether_type = 0;
    7783                 :          0 :         int actions_n = 0;
    7784                 :            :         uint8_t item_ipv6_proto = 0;
    7785                 :          0 :         int fdb_mirror = 0;
    7786                 :            :         int modify_after_mirror = 0;
    7787                 :            :         const struct rte_flow_item *geneve_item = NULL;
    7788                 :            :         const struct rte_flow_item *gre_item = NULL;
    7789                 :            :         const struct rte_flow_item *gtp_item = NULL;
    7790                 :            :         const struct rte_flow_action_raw_decap *decap;
    7791                 :            :         const struct rte_flow_action_raw_encap *encap;
    7792                 :            :         const struct rte_flow_action_rss *rss = NULL;
    7793                 :          0 :         const struct rte_flow_action_rss *sample_rss = NULL;
    7794                 :          0 :         const struct rte_flow_action_count *sample_count = NULL;
    7795                 :          0 :         const struct rte_flow_item_ecpri nic_ecpri_mask = {
    7796                 :            :                 .hdr = {
    7797                 :            :                         .common = {
    7798                 :            :                                 .u32 =
    7799                 :            :                                 RTE_BE32(((const struct rte_ecpri_common_hdr) {
    7800                 :            :                                         .type = 0xFF,
    7801                 :            :                                         }).u32),
    7802                 :            :                         },
    7803                 :            :                         .dummy[0] = 0xffffffff,
    7804                 :            :                 },
    7805                 :            :         };
    7806                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    7807                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
    7808                 :            :         uint16_t queue_index = 0xFFFF;
    7809                 :            :         const struct rte_flow_item_vlan *vlan_m = NULL;
    7810                 :            :         uint32_t rw_act_num = 0;
    7811                 :            :         uint64_t is_root;
    7812                 :            :         const struct mlx5_flow_tunnel *tunnel;
    7813                 :            :         enum mlx5_tof_rule_type tof_rule_type;
    7814                 :          0 :         struct flow_grp_info grp_info = {
    7815                 :            :                 .external = !!external,
    7816                 :          0 :                 .transfer = !!attr->transfer,
    7817                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
    7818                 :            :                 .std_tbl_fix = true,
    7819                 :            :         };
    7820                 :            :         const struct rte_eth_hairpin_conf *conf;
    7821                 :          0 :         const struct rte_flow_item *integrity_items[2] = {NULL, NULL};
    7822                 :            :         const struct rte_flow_item *port_id_item = NULL;
    7823                 :          0 :         bool def_policy = false;
    7824                 :            :         bool shared_count = false;
    7825                 :            :         uint16_t udp_dport = 0;
    7826                 :          0 :         uint32_t tag_id = 0, tag_bitmap = 0;
    7827                 :            :         const struct rte_flow_action_age *non_shared_age = NULL;
    7828                 :            :         const struct rte_flow_action_count *count = NULL;
    7829                 :            :         const struct rte_flow_action_port_id *port = NULL;
    7830                 :            :         const struct mlx5_rte_flow_item_tag *mlx5_tag;
    7831                 :          0 :         struct mlx5_priv *act_priv = NULL;
    7832                 :            :         int aso_after_sample = 0;
    7833                 :            :         struct mlx5_priv *port_priv = NULL;
    7834                 :          0 :         uint64_t sub_action_flags = 0;
    7835                 :          0 :         uint16_t sample_port_id = 0;
    7836                 :            :         uint16_t port_id = 0;
    7837                 :            : 
    7838         [ #  # ]:          0 :         if (items == NULL)
    7839                 :            :                 return -1;
    7840                 :            :         tunnel = is_tunnel_offload_active(dev) ?
    7841         [ #  # ]:          0 :                  mlx5_get_tof(items, actions, &tof_rule_type) : NULL;
    7842         [ #  # ]:          0 :         if (tunnel) {
    7843         [ #  # ]:          0 :                 if (!dev_conf->dv_flow_en)
    7844                 :          0 :                         return rte_flow_error_set
    7845                 :            :                                 (error, ENOTSUP,
    7846                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    7847                 :            :                                  NULL, "tunnel offload requires DV flow interface");
    7848         [ #  # ]:          0 :                 if (priv->representor)
    7849                 :          0 :                         return rte_flow_error_set
    7850                 :            :                                 (error, ENOTSUP,
    7851                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    7852                 :            :                                  NULL, "decap not supported for VF representor");
    7853         [ #  # ]:          0 :                 if (tof_rule_type == MLX5_TUNNEL_OFFLOAD_SET_RULE)
    7854                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;
    7855         [ #  # ]:          0 :                 else if (tof_rule_type == MLX5_TUNNEL_OFFLOAD_MATCH_RULE)
    7856                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_MATCH |
    7857                 :            :                                         MLX5_FLOW_ACTION_DECAP;
    7858                 :          0 :                 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
    7859                 :            :                                         (dev, attr, tunnel, tof_rule_type);
    7860                 :            :         }
    7861                 :          0 :         ret = flow_dv_validate_attributes(dev, tunnel, attr, &grp_info, error);
    7862         [ #  # ]:          0 :         if (ret < 0)
    7863                 :            :                 return ret;
    7864                 :          0 :         is_root = (uint64_t)ret;
    7865         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
    7866                 :            :                 enum mlx5_l3_tunnel_detection l3_tunnel_detection;
    7867                 :            :                 uint64_t l3_tunnel_flag;
    7868                 :          0 :                 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
    7869                 :          0 :                 int type = items->type;
    7870                 :            : 
    7871                 :            :                 if (!mlx5_flow_os_item_supported(type))
    7872                 :            :                         return rte_flow_error_set(error, ENOTSUP,
    7873                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    7874                 :            :                                                   NULL, "item not supported");
    7875   [ #  #  #  #  :          0 :                 switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    7876                 :            :                 case RTE_FLOW_ITEM_TYPE_VOID:
    7877                 :            :                         break;
    7878                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ESP:
    7879                 :          0 :                         ret = mlx5_flow_os_validate_item_esp(dev, items, item_flags,
    7880                 :            :                                                              next_protocol, false, error);
    7881         [ #  # ]:          0 :                         if (ret < 0)
    7882                 :          0 :                                 return ret;
    7883                 :          0 :                         last_item = MLX5_FLOW_ITEM_ESP;
    7884                 :          0 :                         break;
    7885                 :          0 :                 case RTE_FLOW_ITEM_TYPE_PORT_ID:
    7886                 :          0 :                         ret = flow_dv_validate_item_port_id
    7887                 :            :                                         (dev, items, attr, item_flags, &act_priv, error);
    7888         [ #  # ]:          0 :                         if (ret < 0)
    7889                 :          0 :                                 return ret;
    7890                 :          0 :                         last_item = MLX5_FLOW_ITEM_PORT_ID;
    7891                 :            :                         port_id_item = items;
    7892                 :          0 :                         break;
    7893                 :          0 :                 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
    7894                 :            :                 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
    7895                 :          0 :                         ret = flow_dv_validate_item_represented_port
    7896                 :            :                                         (dev, items, attr, item_flags, &act_priv, error);
    7897         [ #  # ]:          0 :                         if (ret < 0)
    7898                 :          0 :                                 return ret;
    7899                 :          0 :                         last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
    7900                 :            :                         port_id_item = items;
    7901                 :          0 :                         break;
    7902                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    7903                 :          0 :                         ret = mlx5_flow_validate_item_eth(dev, items, item_flags,
    7904                 :            :                                                           true, error);
    7905         [ #  # ]:          0 :                         if (ret < 0)
    7906                 :          0 :                                 return ret;
    7907         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
    7908                 :            :                                              MLX5_FLOW_LAYER_OUTER_L2;
    7909   [ #  #  #  # ]:          0 :                         if (items->mask != NULL && items->spec != NULL) {
    7910                 :          0 :                                 ether_type =
    7911                 :            :                                         ((const struct rte_flow_item_eth *)
    7912                 :            :                                          items->spec)->hdr.ether_type;
    7913                 :          0 :                                 ether_type &=
    7914                 :            :                                         ((const struct rte_flow_item_eth *)
    7915                 :          0 :                                          items->mask)->hdr.ether_type;
    7916         [ #  # ]:          0 :                                 ether_type = rte_be_to_cpu_16(ether_type);
    7917                 :            :                         } else {
    7918                 :            :                                 ether_type = 0;
    7919                 :            :                         }
    7920                 :            :                         break;
    7921                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    7922                 :          0 :                         ret = mlx5_flow_dv_validate_item_vlan(items, item_flags,
    7923                 :            :                                                               dev, error);
    7924         [ #  # ]:          0 :                         if (ret < 0)
    7925                 :          0 :                                 return ret;
    7926         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
    7927                 :            :                                              MLX5_FLOW_LAYER_OUTER_VLAN;
    7928   [ #  #  #  # ]:          0 :                         if (items->mask != NULL && items->spec != NULL) {
    7929                 :          0 :                                 ether_type =
    7930                 :            :                                         ((const struct rte_flow_item_vlan *)
    7931                 :            :                                          items->spec)->hdr.eth_proto;
    7932                 :          0 :                                 ether_type &=
    7933                 :            :                                         ((const struct rte_flow_item_vlan *)
    7934                 :          0 :                                          items->mask)->hdr.eth_proto;
    7935         [ #  # ]:          0 :                                 ether_type = rte_be_to_cpu_16(ether_type);
    7936                 :            :                         } else {
    7937                 :            :                                 ether_type = 0;
    7938                 :            :                         }
    7939                 :            :                         /* Store outer VLAN mask for of_push_vlan action. */
    7940         [ #  # ]:          0 :                         if (!tunnel)
    7941                 :            :                                 vlan_m = items->mask;
    7942                 :            :                         break;
    7943                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    7944                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7945                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7946                 :            :                         l3_tunnel_detection =
    7947                 :            :                                 mlx5_flow_tunnel_ip_check(items, next_protocol,
    7948                 :            :                                                           item_flags,
    7949                 :            :                                                           &l3_tunnel_flag);
    7950                 :            :                         /*
    7951                 :            :                          * explicitly allow inner IPIP match
    7952                 :            :                          */
    7953                 :            :                         if (l3_tunnel_detection == l3_tunnel_outer) {
    7954                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7955                 :            :                                 tunnel = 1;
    7956                 :            :                         }
    7957                 :          0 :                         ret = mlx5_flow_dv_validate_item_ipv4(dev, items,
    7958                 :            :                                                               item_flags,
    7959                 :            :                                                               last_item,
    7960                 :            :                                                               ether_type,
    7961                 :            :                                                               &nic_ipv4_mask,
    7962                 :            :                                                               error);
    7963         [ #  # ]:          0 :                         if (ret < 0)
    7964                 :          0 :                                 return ret;
    7965         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
    7966                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV4;
    7967         [ #  # ]:          0 :                         if (l3_tunnel_detection == l3_tunnel_outer)
    7968                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7969                 :            :                         break;
    7970                 :            :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    7971                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    7972                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    7973                 :            :                         l3_tunnel_detection =
    7974                 :            :                                 mlx5_flow_tunnel_ip_check(items, next_protocol,
    7975                 :            :                                                           item_flags,
    7976                 :            :                                                           &l3_tunnel_flag);
    7977                 :            :                         /*
    7978                 :            :                          * explicitly allow inner IPIP match
    7979                 :            :                          */
    7980                 :            :                         if (l3_tunnel_detection == l3_tunnel_outer) {
    7981                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7982                 :            :                                 tunnel = 1;
    7983                 :            :                         }
    7984                 :          0 :                         ret = mlx5_flow_validate_item_ipv6(dev, items,
    7985                 :            :                                                            item_flags,
    7986                 :            :                                                            last_item,
    7987                 :            :                                                            ether_type,
    7988                 :            :                                                            &nic_ipv6_mask,
    7989                 :            :                                                            error);
    7990         [ #  # ]:          0 :                         if (ret < 0)
    7991                 :          0 :                                 return ret;
    7992         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
    7993                 :            :                                              MLX5_FLOW_LAYER_OUTER_L3_IPV6;
    7994         [ #  # ]:          0 :                         if (l3_tunnel_detection == l3_tunnel_outer)
    7995                 :          0 :                                 item_flags |= l3_tunnel_flag;
    7996                 :            :                         break;
    7997                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
    7998                 :          0 :                         ret = flow_dv_validate_item_ipv6_frag_ext(dev, items,
    7999                 :            :                                                                   item_flags,
    8000                 :            :                                                                   error);
    8001         [ #  # ]:          0 :                         if (ret < 0)
    8002                 :          0 :                                 return ret;
    8003         [ #  # ]:          0 :                         last_item = tunnel ?
    8004         [ #  # ]:          0 :                                         MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT :
    8005                 :            :                                         MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT;
    8006                 :            :                         next_protocol = mlx5_flow_l3_next_protocol
    8007                 :            :                                 (items, (enum MLX5_SET_MATCHER)-1);
    8008                 :            :                         break;
    8009                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
    8010                 :          0 :                         ret = mlx5_flow_validate_item_tcp
    8011                 :            :                                                 (dev, items, item_flags,
    8012                 :            :                                                  next_protocol,
    8013                 :            :                                                  &nic_tcp_mask,
    8014                 :            :                                                  error);
    8015         [ #  # ]:          0 :                         if (ret < 0)
    8016                 :          0 :                                 return ret;
    8017         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
    8018                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_TCP;
    8019                 :          0 :                         break;
    8020                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    8021                 :          0 :                         ret = mlx5_flow_validate_item_udp(dev, items, item_flags,
    8022                 :            :                                                           next_protocol,
    8023                 :            :                                                           error);
    8024                 :          0 :                         const struct rte_flow_item_udp *spec = items->spec;
    8025                 :          0 :                         const struct rte_flow_item_udp *mask = items->mask;
    8026         [ #  # ]:          0 :                         if (!mask)
    8027                 :            :                                 mask = &rte_flow_item_udp_mask;
    8028         [ #  # ]:          0 :                         if (spec != NULL)
    8029         [ #  # ]:          0 :                                 udp_dport = rte_be_to_cpu_16
    8030                 :            :                                                 (spec->hdr.dst_port &
    8031                 :            :                                                  mask->hdr.dst_port);
    8032         [ #  # ]:          0 :                         if (ret < 0)
    8033                 :          0 :                                 return ret;
    8034         [ #  # ]:          0 :                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
    8035                 :            :                                              MLX5_FLOW_LAYER_OUTER_L4_UDP;
    8036                 :          0 :                         break;
    8037                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE:
    8038                 :          0 :                         ret = mlx5_flow_validate_item_gre(dev, items, item_flags,
    8039                 :            :                                                           next_protocol, error);
    8040         [ #  # ]:          0 :                         if (ret < 0)
    8041                 :          0 :                                 return ret;
    8042                 :            :                         gre_item = items;
    8043                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE;
    8044                 :          0 :                         break;
    8045                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
    8046                 :          0 :                         ret = mlx5_flow_validate_item_gre_option(dev, items, item_flags,
    8047                 :            :                                                           attr, gre_item, error);
    8048         [ #  # ]:          0 :                         if (ret < 0)
    8049                 :          0 :                                 return ret;
    8050                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE;
    8051                 :          0 :                         break;
    8052                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    8053                 :          0 :                         ret = mlx5_flow_validate_item_nvgre(dev, items,
    8054                 :            :                                                             item_flags,
    8055                 :            :                                                             next_protocol,
    8056                 :            :                                                             error);
    8057         [ #  # ]:          0 :                         if (ret < 0)
    8058                 :          0 :                                 return ret;
    8059                 :          0 :                         last_item = MLX5_FLOW_LAYER_NVGRE;
    8060                 :          0 :                         break;
    8061                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
    8062                 :          0 :                         ret = mlx5_flow_validate_item_gre_key
    8063                 :            :                                 (dev, items, item_flags, gre_item, error);
    8064         [ #  # ]:          0 :                         if (ret < 0)
    8065                 :          0 :                                 return ret;
    8066                 :          0 :                         last_item = MLX5_FLOW_LAYER_GRE_KEY;
    8067                 :          0 :                         break;
    8068                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    8069                 :          0 :                         ret = mlx5_flow_validate_item_vxlan(dev, udp_dport,
    8070                 :            :                                                             items, item_flags,
    8071                 :            :                                                             is_root, error);
    8072         [ #  # ]:          0 :                         if (ret < 0)
    8073                 :          0 :                                 return ret;
    8074                 :          0 :                         last_item = MLX5_FLOW_LAYER_VXLAN;
    8075                 :          0 :                         break;
    8076                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    8077                 :          0 :                         ret = mlx5_flow_validate_item_vxlan_gpe(items,
    8078                 :            :                                                                 item_flags, dev,
    8079                 :            :                                                                 error);
    8080         [ #  # ]:          0 :                         if (ret < 0)
    8081                 :          0 :                                 return ret;
    8082                 :          0 :                         last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
    8083                 :          0 :                         break;
    8084                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
    8085                 :          0 :                         ret = mlx5_flow_validate_item_geneve(items,
    8086                 :            :                                                              item_flags, dev,
    8087                 :            :                                                              error);
    8088         [ #  # ]:          0 :                         if (ret < 0)
    8089                 :          0 :                                 return ret;
    8090                 :            :                         geneve_item = items;
    8091                 :          0 :                         last_item = MLX5_FLOW_LAYER_GENEVE;
    8092                 :          0 :                         break;
    8093                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
    8094                 :          0 :                         ret = mlx5_flow_validate_item_geneve_opt(items,
    8095                 :            :                                                                  last_item,
    8096                 :            :                                                                  geneve_item,
    8097                 :            :                                                                  dev,
    8098                 :            :                                                                  error);
    8099         [ #  # ]:          0 :                         if (ret < 0)
    8100                 :          0 :                                 return ret;
    8101                 :          0 :                         last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
    8102                 :          0 :                         break;
    8103                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MPLS:
    8104                 :          0 :                         ret = mlx5_flow_validate_item_mpls(dev, items,
    8105                 :            :                                                            item_flags,
    8106                 :            :                                                            last_item, error);
    8107         [ #  # ]:          0 :                         if (ret < 0)
    8108                 :          0 :                                 return ret;
    8109                 :          0 :                         last_item = MLX5_FLOW_LAYER_MPLS;
    8110                 :          0 :                         break;
    8111                 :            : 
    8112                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MARK:
    8113                 :          0 :                         ret = flow_dv_validate_item_mark(dev, items, attr,
    8114                 :            :                                                          error);
    8115         [ #  # ]:          0 :                         if (ret < 0)
    8116                 :          0 :                                 return ret;
    8117                 :          0 :                         last_item = MLX5_FLOW_ITEM_MARK;
    8118                 :          0 :                         break;
    8119                 :          0 :                 case RTE_FLOW_ITEM_TYPE_META:
    8120                 :          0 :                         ret = flow_dv_validate_item_meta(dev, items, attr,
    8121                 :            :                                                          error);
    8122         [ #  # ]:          0 :                         if (ret < 0)
    8123                 :          0 :                                 return ret;
    8124                 :          0 :                         last_item = MLX5_FLOW_ITEM_METADATA;
    8125                 :          0 :                         break;
    8126                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP:
    8127                 :          0 :                         ret = mlx5_flow_validate_item_icmp(dev, items, item_flags,
    8128                 :            :                                                            next_protocol,
    8129                 :            :                                                            error);
    8130         [ #  # ]:          0 :                         if (ret < 0)
    8131                 :          0 :                                 return ret;
    8132                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP;
    8133                 :          0 :                         break;
    8134                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6:
    8135                 :          0 :                         ret = mlx5_flow_validate_item_icmp6(dev, items, item_flags,
    8136                 :            :                                                             next_protocol,
    8137                 :            :                                                             error);
    8138         [ #  # ]:          0 :                         if (ret < 0)
    8139                 :          0 :                                 return ret;
    8140                 :            :                         item_ipv6_proto = IPPROTO_ICMPV6;
    8141                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8142                 :          0 :                         break;
    8143                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
    8144                 :            :                 case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
    8145                 :          0 :                         ret = mlx5_flow_validate_item_icmp6_echo(dev, items,
    8146                 :            :                                                                  item_flags,
    8147                 :            :                                                                  next_protocol,
    8148                 :            :                                                                  error);
    8149         [ #  # ]:          0 :                         if (ret < 0)
    8150                 :          0 :                                 return ret;
    8151                 :            :                         item_ipv6_proto = IPPROTO_ICMPV6;
    8152                 :          0 :                         last_item = MLX5_FLOW_LAYER_ICMP6;
    8153                 :          0 :                         break;
    8154                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TAG:
    8155                 :          0 :                         ret = flow_dv_validate_item_tag(dev, items, &tag_bitmap,
    8156                 :            :                                                         attr, error);
    8157         [ #  # ]:          0 :                         if (ret < 0)
    8158                 :          0 :                                 return ret;
    8159                 :          0 :                         last_item = MLX5_FLOW_ITEM_TAG;
    8160                 :          0 :                         break;
    8161                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
    8162                 :            :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
    8163                 :          0 :                         last_item = MLX5_FLOW_ITEM_SQ;
    8164                 :          0 :                         break;
    8165                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
    8166                 :          0 :                         mlx5_tag = (const struct mlx5_rte_flow_item_tag *)items->spec;
    8167         [ #  # ]:          0 :                         if (tag_bitmap & (1 << mlx5_tag->id))
    8168                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8169                 :            :                                                           RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
    8170                 :            :                                                           items->spec,
    8171                 :            :                                                           "Duplicated tag index");
    8172                 :          0 :                         tag_bitmap |= 1 << mlx5_tag->id;
    8173                 :          0 :                         break;
    8174                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP:
    8175                 :          0 :                         ret = mlx5_flow_dv_validate_item_gtp(dev, items,
    8176                 :            :                                                              item_flags,
    8177                 :            :                                                              error);
    8178         [ #  # ]:          0 :                         if (ret < 0)
    8179                 :          0 :                                 return ret;
    8180                 :            :                         gtp_item = items;
    8181                 :          0 :                         last_item = MLX5_FLOW_LAYER_GTP;
    8182                 :          0 :                         break;
    8183                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
    8184                 :          0 :                         ret = mlx5_flow_dv_validate_item_gtp_psc(dev, items,
    8185                 :            :                                                                  last_item,
    8186                 :            :                                                                  gtp_item,
    8187                 :            :                                                                  is_root, error);
    8188         [ #  # ]:          0 :                         if (ret < 0)
    8189                 :          0 :                                 return ret;
    8190                 :          0 :                         last_item = MLX5_FLOW_LAYER_GTP_PSC;
    8191                 :          0 :                         break;
    8192                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ECPRI:
    8193                 :            :                         /* Capacity will be checked in the translate stage. */
    8194                 :          0 :                         ret = mlx5_flow_validate_item_ecpri(dev, items,
    8195                 :            :                                                             item_flags,
    8196                 :            :                                                             last_item,
    8197                 :            :                                                             ether_type,
    8198                 :            :                                                             &nic_ecpri_mask,
    8199                 :            :                                                             error);
    8200         [ #  # ]:          0 :                         if (ret < 0)
    8201                 :          0 :                                 return ret;
    8202                 :          0 :                         last_item = MLX5_FLOW_LAYER_ECPRI;
    8203                 :          0 :                         break;
    8204                 :          0 :                 case RTE_FLOW_ITEM_TYPE_INTEGRITY:
    8205                 :          0 :                         ret = flow_dv_validate_item_integrity(dev, items,
    8206                 :            :                                                               item_flags,
    8207                 :            :                                                               &last_item,
    8208                 :            :                                                               integrity_items,
    8209                 :            :                                                               error);
    8210         [ #  # ]:          0 :                         if (ret < 0)
    8211                 :          0 :                                 return ret;
    8212                 :            :                         break;
    8213                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
    8214                 :          0 :                         ret = mlx5_flow_dv_validate_item_aso_ct(dev, items,
    8215                 :            :                                                                 &item_flags,
    8216                 :            :                                                                 error);
    8217         [ #  # ]:          0 :                         if (ret < 0)
    8218                 :          0 :                                 return ret;
    8219                 :          0 :                         last_item = MLX5_FLOW_LAYER_ASO_CT;
    8220                 :          0 :                         break;
    8221                 :            :                 case MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL:
    8222                 :            :                         /* tunnel offload item was processed before
    8223                 :            :                          * list it here as a supported type
    8224                 :            :                          */
    8225                 :            :                         break;
    8226                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
    8227                 :          0 :                         ret = flow_dv_validate_item_flex(dev, items, item_flags,
    8228                 :            :                                                          &last_item,
    8229                 :            :                                                          tunnel != 0, error);
    8230         [ #  # ]:          0 :                         if (ret < 0)
    8231                 :          0 :                                 return ret;
    8232                 :            :                         /* Reset for next proto, it is unknown. */
    8233                 :            :                         next_protocol = 0xff;
    8234                 :            :                         break;
    8235                 :          0 :                 case RTE_FLOW_ITEM_TYPE_METER_COLOR:
    8236                 :          0 :                         ret = flow_dv_validate_item_meter_color(dev, items,
    8237                 :            :                                                                 attr, error);
    8238         [ #  # ]:          0 :                         if (ret < 0)
    8239                 :          0 :                                 return ret;
    8240                 :          0 :                         last_item = MLX5_FLOW_ITEM_METER_COLOR;
    8241                 :          0 :                         break;
    8242                 :          0 :                 case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
    8243                 :          0 :                         ret = flow_dv_validate_item_aggr_affinity(dev, items,
    8244                 :            :                                                                   attr, error);
    8245         [ #  # ]:          0 :                         if (ret < 0)
    8246                 :          0 :                                 return ret;
    8247                 :          0 :                         last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
    8248                 :          0 :                         break;
    8249                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IB_BTH:
    8250                 :          0 :                         ret = mlx5_flow_validate_item_ib_bth(dev, udp_dport,
    8251                 :            :                                                             items, is_root, error);
    8252         [ #  # ]:          0 :                         if (ret < 0)
    8253                 :          0 :                                 return ret;
    8254                 :            : 
    8255                 :          0 :                         last_item = MLX5_FLOW_ITEM_IB_BTH;
    8256                 :          0 :                         break;
    8257                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NSH:
    8258                 :          0 :                         ret = mlx5_flow_validate_item_nsh(dev, items, error);
    8259         [ #  # ]:          0 :                         if (ret < 0)
    8260                 :          0 :                                 return ret;
    8261                 :          0 :                         last_item = MLX5_FLOW_ITEM_NSH;
    8262                 :          0 :                         break;
    8263                 :          0 :                 default:
    8264                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8265                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    8266                 :            :                                                   NULL, "item not supported");
    8267                 :            :                 }
    8268                 :          0 :                 item_flags |= last_item;
    8269                 :            :         }
    8270         [ #  # ]:          0 :         if (item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
    8271                 :          0 :                 ret = flow_dv_validate_item_integrity_post(integrity_items,
    8272                 :            :                                                            item_flags, error);
    8273         [ #  # ]:          0 :                 if (ret)
    8274                 :            :                         return ret;
    8275                 :            :         }
    8276         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    8277                 :          0 :                 int type = actions->type;
    8278                 :            : 
    8279                 :            :                 if (!mlx5_flow_os_action_supported(type))
    8280                 :            :                         return rte_flow_error_set(error, ENOTSUP,
    8281                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8282                 :            :                                                   actions,
    8283                 :            :                                                   "action not supported");
    8284         [ #  # ]:          0 :                 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
    8285                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8286                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8287                 :            :                                                   actions, "too many actions");
    8288         [ #  # ]:          0 :                 if (action_flags &
    8289                 :            :                         MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
    8290                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8291                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8292                 :            :                                 NULL, "meter action with policy "
    8293                 :            :                                 "must be the last action");
    8294   [ #  #  #  #  :          0 :                 switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    8295                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    8296                 :            :                         break;
    8297                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
    8298                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    8299                 :          0 :                         ret = flow_dv_validate_action_port_id(dev,
    8300                 :            :                                                               action_flags,
    8301                 :            :                                                               actions,
    8302                 :            :                                                               attr,
    8303                 :            :                                                               error);
    8304         [ #  # ]:          0 :                         if (ret)
    8305                 :          0 :                                 return ret;
    8306         [ #  # ]:          0 :                         if (type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
    8307                 :          0 :                                 port = (const struct rte_flow_action_port_id *)
    8308                 :            :                                         actions->conf;
    8309         [ #  # ]:          0 :                                 port_id = port->original ? dev->data->port_id : port->id;
    8310                 :            :                         } else {
    8311                 :          0 :                                 port_id = ((const struct rte_flow_action_ethdev *)
    8312                 :          0 :                                         actions->conf)->port_id;
    8313                 :            :                         }
    8314                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
    8315                 :          0 :                         ++actions_n;
    8316                 :          0 :                         break;
    8317                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    8318                 :          0 :                         ret = flow_dv_validate_action_flag(dev, 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_FLAG |
    8328                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    8329         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8330                 :            :                                         modify_after_mirror = 1;
    8331                 :            : 
    8332                 :            :                         } else {
    8333                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_FLAG;
    8334                 :          0 :                                 ++actions_n;
    8335                 :            :                         }
    8336                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_MARK;
    8337                 :          0 :                         break;
    8338                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    8339                 :          0 :                         ret = flow_dv_validate_action_mark(dev, actions,
    8340                 :            :                                                            action_flags,
    8341                 :            :                                                            attr, error);
    8342         [ #  # ]:          0 :                         if (ret < 0)
    8343                 :          0 :                                 return ret;
    8344         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
    8345                 :            :                                 /* Count all modify-header actions as one. */
    8346         [ #  # ]:          0 :                                 if (!(action_flags &
    8347                 :            :                                       MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8348                 :          0 :                                         ++actions_n;
    8349                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK |
    8350                 :            :                                                 MLX5_FLOW_ACTION_MARK_EXT;
    8351         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8352                 :            :                                         modify_after_mirror = 1;
    8353                 :            :                         } else {
    8354                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK;
    8355                 :          0 :                                 ++actions_n;
    8356                 :            :                         }
    8357                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_MARK;
    8358                 :          0 :                         break;
    8359                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_META:
    8360         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    8361                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8362                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8363                 :            :                                                   actions,
    8364                 :            :                                                   "action not supported");
    8365                 :          0 :                         ret = flow_dv_validate_action_set_meta(dev, actions,
    8366                 :            :                                                                action_flags,
    8367                 :            :                                                                attr, error);
    8368         [ #  # ]:          0 :                         if (ret < 0)
    8369                 :          0 :                                 return ret;
    8370                 :            :                         /* Count all modify-header actions as one action. */
    8371         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8372                 :          0 :                                 ++actions_n;
    8373         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8374                 :            :                                 modify_after_mirror = 1;
    8375                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_META;
    8376                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_META;
    8377                 :          0 :                         break;
    8378                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
    8379                 :          0 :                         ret = flow_dv_validate_action_set_tag(dev, actions,
    8380                 :            :                                                               action_flags,
    8381                 :            :                                                               attr, error);
    8382         [ #  # ]:          0 :                         if (ret < 0)
    8383                 :          0 :                                 return ret;
    8384                 :            :                         /* Count all modify-header actions as one action. */
    8385         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8386                 :          0 :                                 ++actions_n;
    8387         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8388                 :            :                                 modify_after_mirror = 1;
    8389                 :          0 :                         tag_id = ((const struct rte_flow_action_set_tag *)
    8390                 :          0 :                                   actions->conf)->index;
    8391                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
    8392                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8393                 :          0 :                         break;
    8394                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
    8395                 :          0 :                         ret = mlx5_flow_validate_action_drop(dev, is_root,
    8396                 :            :                                                              attr, error);
    8397         [ #  # ]:          0 :                         if (ret < 0)
    8398                 :          0 :                                 return ret;
    8399                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
    8400                 :          0 :                         ++actions_n;
    8401                 :          0 :                         break;
    8402                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    8403                 :          0 :                         ret = mlx5_flow_validate_action_queue(actions,
    8404                 :            :                                                               action_flags, dev,
    8405                 :            :                                                               attr, error);
    8406         [ #  # ]:          0 :                         if (ret < 0)
    8407                 :          0 :                                 return ret;
    8408                 :          0 :                         queue_index = ((const struct rte_flow_action_queue *)
    8409                 :          0 :                                                         (actions->conf))->index;
    8410                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
    8411                 :          0 :                         ++actions_n;
    8412                 :          0 :                         break;
    8413                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    8414                 :          0 :                         rss = actions->conf;
    8415                 :          0 :                         ret = mlx5_flow_validate_action_rss(actions,
    8416                 :            :                                                             action_flags, dev,
    8417                 :            :                                                             attr, item_flags,
    8418                 :            :                                                             error);
    8419         [ #  # ]:          0 :                         if (ret < 0)
    8420                 :          0 :                                 return ret;
    8421         [ #  # ]:          0 :                         if (rss && sample_rss &&
    8422         [ #  # ]:          0 :                             (sample_rss->level != rss->level ||
    8423         [ #  # ]:          0 :                             sample_rss->types != rss->types))
    8424                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8425                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8426                 :            :                                         NULL,
    8427                 :            :                                         "Can't use the different RSS types "
    8428                 :            :                                         "or level in the same flow");
    8429   [ #  #  #  # ]:          0 :                         if (rss != NULL && rss->queue_num)
    8430                 :          0 :                                 queue_index = rss->queue[0];
    8431                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
    8432                 :          0 :                         ++actions_n;
    8433                 :          0 :                         break;
    8434                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
    8435                 :            :                         ret =
    8436                 :          0 :                         mlx5_flow_validate_action_default_miss(action_flags,
    8437                 :            :                                         attr, error);
    8438         [ #  # ]:          0 :                         if (ret < 0)
    8439                 :          0 :                                 return ret;
    8440                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
    8441                 :          0 :                         ++actions_n;
    8442                 :          0 :                         break;
    8443                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
    8444                 :            :                         shared_count = true;
    8445                 :            :                         /* fall-through. */
    8446                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
    8447                 :          0 :                         ret = flow_dv_validate_action_count(dev, shared_count,
    8448                 :            :                                                             action_flags,
    8449                 :            :                                                             is_root, error);
    8450         [ #  # ]:          0 :                         if (ret < 0)
    8451                 :          0 :                                 return ret;
    8452                 :          0 :                         count = actions->conf;
    8453                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
    8454                 :          0 :                         ++actions_n;
    8455                 :          0 :                         break;
    8456                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    8457         [ #  # ]:          0 :                         if (flow_dv_validate_action_pop_vlan(dev,
    8458                 :            :                                                              action_flags,
    8459                 :            :                                                              actions,
    8460                 :            :                                                              item_flags, attr,
    8461                 :            :                                                              error))
    8462                 :          0 :                                 return -rte_errno;
    8463         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8464                 :            :                                 modify_after_mirror = 1;
    8465                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
    8466                 :          0 :                         ++actions_n;
    8467                 :          0 :                         break;
    8468                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    8469                 :          0 :                         ret = flow_dv_validate_action_push_vlan(dev,
    8470                 :            :                                                                 action_flags,
    8471                 :            :                                                                 vlan_m,
    8472                 :            :                                                                 actions, attr,
    8473                 :            :                                                                 error);
    8474         [ #  # ]:          0 :                         if (ret < 0)
    8475                 :          0 :                                 return ret;
    8476         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8477                 :            :                                 modify_after_mirror = 1;
    8478                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
    8479                 :          0 :                         ++actions_n;
    8480                 :          0 :                         break;
    8481                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    8482                 :          0 :                         ret = flow_dv_validate_action_set_vlan_pcp
    8483                 :            :                                                 (action_flags, actions, error);
    8484         [ #  # ]:          0 :                         if (ret < 0)
    8485                 :          0 :                                 return ret;
    8486         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8487                 :            :                                 modify_after_mirror = 1;
    8488                 :            :                         /* Count PCP with push_vlan command. */
    8489                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;
    8490                 :          0 :                         break;
    8491                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    8492                 :          0 :                         ret = flow_dv_validate_action_set_vlan_vid
    8493                 :            :                                                 (item_flags, action_flags,
    8494                 :            :                                                  actions, error);
    8495         [ #  # ]:          0 :                         if (ret < 0)
    8496                 :          0 :                                 return ret;
    8497         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8498                 :            :                                 modify_after_mirror = 1;
    8499                 :            :                         /* Count VID with push_vlan command. */
    8500                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
    8501                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_VID;
    8502                 :          0 :                         break;
    8503                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    8504                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
    8505                 :          0 :                         ret = mlx5_flow_dv_validate_action_l2_encap(dev,
    8506                 :            :                                                                     action_flags,
    8507                 :            :                                                                     actions,
    8508                 :            :                                                                     attr,
    8509                 :            :                                                                     error);
    8510         [ #  # ]:          0 :                         if (ret < 0)
    8511                 :          0 :                                 return ret;
    8512                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
    8513                 :          0 :                         ++actions_n;
    8514                 :          0 :                         break;
    8515                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    8516                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
    8517                 :          0 :                         ret = mlx5_flow_dv_validate_action_decap(dev,
    8518                 :            :                                                                  action_flags,
    8519                 :            :                                                                  actions,
    8520                 :            :                                                                  item_flags,
    8521                 :            :                                                                  attr, error);
    8522         [ #  # ]:          0 :                         if (ret < 0)
    8523                 :          0 :                                 return ret;
    8524         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8525                 :            :                                 modify_after_mirror = 1;
    8526                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
    8527                 :          0 :                         ++actions_n;
    8528                 :          0 :                         break;
    8529                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
    8530                 :          0 :                         ret = mlx5_flow_dv_validate_action_raw_encap_decap
    8531                 :          0 :                                 (dev, NULL, actions->conf, attr, &action_flags,
    8532                 :            :                                  &actions_n, actions, item_flags, error);
    8533         [ #  # ]:          0 :                         if (ret < 0)
    8534                 :          0 :                                 return ret;
    8535                 :            :                         break;
    8536                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
    8537                 :          0 :                         decap = actions->conf;
    8538         [ #  # ]:          0 :                         while ((++actions)->type == RTE_FLOW_ACTION_TYPE_VOID)
    8539                 :            :                                 ;
    8540         [ #  # ]:          0 :                         if (actions->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
    8541                 :            :                                 encap = NULL;
    8542                 :            :                                 actions--;
    8543                 :            :                         } else {
    8544                 :          0 :                                 encap = actions->conf;
    8545                 :            :                         }
    8546         [ #  # ]:          0 :                         ret = mlx5_flow_dv_validate_action_raw_encap_decap
    8547                 :            :                                 (dev,
    8548                 :            :                                  decap ? decap : &empty_decap, encap,
    8549                 :            :                                  attr, &action_flags, &actions_n,
    8550                 :            :                                  actions, item_flags, error);
    8551         [ #  # ]:          0 :                         if (ret < 0)
    8552                 :          0 :                                 return ret;
    8553         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) &&
    8554                 :            :                             (action_flags & MLX5_FLOW_ACTION_DECAP))
    8555                 :            :                                 modify_after_mirror = 1;
    8556                 :            :                         break;
    8557                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
    8558                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    8559                 :          0 :                         ret = flow_dv_validate_action_modify_mac(action_flags,
    8560                 :            :                                                                  actions,
    8561                 :            :                                                                  item_flags,
    8562                 :            :                                                                  error);
    8563         [ #  # ]:          0 :                         if (ret < 0)
    8564                 :          0 :                                 return ret;
    8565                 :            :                         /* Count all modify-header actions as one action. */
    8566         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8567                 :          0 :                                 ++actions_n;
    8568                 :          0 :                         action_flags |= actions->type ==
    8569                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
    8570         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_MAC_SRC :
    8571                 :            :                                                 MLX5_FLOW_ACTION_SET_MAC_DST;
    8572         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8573                 :            :                                 modify_after_mirror = 1;
    8574                 :            :                         /*
    8575                 :            :                          * Even if the source and destination MAC addresses have
    8576                 :            :                          * overlap in the header with 4B alignment, the convert
    8577                 :            :                          * function will handle them separately and 4 SW actions
    8578                 :            :                          * will be created. And 2 actions will be added each
    8579                 :            :                          * time no matter how many bytes of address will be set.
    8580                 :            :                          */
    8581                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_MAC;
    8582                 :          0 :                         break;
    8583                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
    8584                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
    8585                 :          0 :                         ret = flow_dv_validate_action_modify_ipv4(action_flags,
    8586                 :            :                                                                   actions,
    8587                 :            :                                                                   item_flags,
    8588                 :            :                                                                   error);
    8589         [ #  # ]:          0 :                         if (ret < 0)
    8590                 :          0 :                                 return ret;
    8591                 :            :                         /* Count all modify-header actions as one action. */
    8592         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8593                 :          0 :                                 ++actions_n;
    8594         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8595                 :            :                                 modify_after_mirror = 1;
    8596                 :          0 :                         action_flags |= actions->type ==
    8597                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
    8598         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_IPV4_SRC :
    8599                 :            :                                                 MLX5_FLOW_ACTION_SET_IPV4_DST;
    8600                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_IPV4;
    8601                 :          0 :                         break;
    8602                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
    8603                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
    8604                 :          0 :                         ret = flow_dv_validate_action_modify_ipv6(action_flags,
    8605                 :            :                                                                   actions,
    8606                 :            :                                                                   item_flags,
    8607                 :            :                                                                   error);
    8608         [ #  # ]:          0 :                         if (ret < 0)
    8609                 :          0 :                                 return ret;
    8610         [ #  # ]:          0 :                         if (item_ipv6_proto == IPPROTO_ICMPV6)
    8611                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8612                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    8613                 :            :                                         actions,
    8614                 :            :                                         "Can't change header "
    8615                 :            :                                         "with ICMPv6 proto");
    8616                 :            :                         /* Count all modify-header actions as one action. */
    8617         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8618                 :          0 :                                 ++actions_n;
    8619         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8620                 :            :                                 modify_after_mirror = 1;
    8621                 :          0 :                         action_flags |= actions->type ==
    8622                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
    8623         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_IPV6_SRC :
    8624                 :            :                                                 MLX5_FLOW_ACTION_SET_IPV6_DST;
    8625                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_IPV6;
    8626                 :          0 :                         break;
    8627                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
    8628                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    8629                 :          0 :                         ret = flow_dv_validate_action_modify_tp(action_flags,
    8630                 :            :                                                                 actions,
    8631                 :            :                                                                 item_flags,
    8632                 :            :                                                                 error);
    8633         [ #  # ]:          0 :                         if (ret < 0)
    8634                 :          0 :                                 return ret;
    8635                 :            :                         /* Count all modify-header actions as one action. */
    8636         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8637                 :          0 :                                 ++actions_n;
    8638         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8639                 :            :                                 modify_after_mirror = 1;
    8640                 :          0 :                         action_flags |= actions->type ==
    8641                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
    8642         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_TP_SRC :
    8643                 :            :                                                 MLX5_FLOW_ACTION_SET_TP_DST;
    8644                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_PORT;
    8645                 :          0 :                         break;
    8646                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
    8647                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
    8648                 :          0 :                         ret = flow_dv_validate_action_modify_ttl(action_flags,
    8649                 :            :                                                                  actions,
    8650                 :            :                                                                  item_flags,
    8651                 :            :                                                                  error);
    8652         [ #  # ]:          0 :                         if (ret < 0)
    8653                 :          0 :                                 return ret;
    8654                 :            :                         /* Count all modify-header actions as one action. */
    8655         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8656                 :          0 :                                 ++actions_n;
    8657         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8658                 :            :                                 modify_after_mirror = 1;
    8659                 :          0 :                         action_flags |= actions->type ==
    8660                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TTL ?
    8661         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_SET_TTL :
    8662                 :            :                                                 MLX5_FLOW_ACTION_DEC_TTL;
    8663                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TTL;
    8664                 :          0 :                         break;
    8665                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
    8666                 :          0 :                         ret = flow_dv_validate_action_jump(dev, tunnel, actions,
    8667                 :            :                                                            action_flags,
    8668                 :            :                                                            attr, external,
    8669                 :            :                                                            error);
    8670         [ #  # ]:          0 :                         if (ret)
    8671                 :          0 :                                 return ret;
    8672                 :          0 :                         ++actions_n;
    8673                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
    8674                 :          0 :                         break;
    8675                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
    8676                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
    8677                 :          0 :                         ret = flow_dv_validate_action_modify_tcp_seq
    8678                 :            :                                                                 (action_flags,
    8679                 :            :                                                                  actions,
    8680                 :            :                                                                  item_flags,
    8681                 :            :                                                                  error);
    8682         [ #  # ]:          0 :                         if (ret < 0)
    8683                 :          0 :                                 return ret;
    8684                 :            :                         /* Count all modify-header actions as one action. */
    8685         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8686                 :          0 :                                 ++actions_n;
    8687         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8688                 :            :                                 modify_after_mirror = 1;
    8689                 :          0 :                         action_flags |= actions->type ==
    8690                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
    8691         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_INC_TCP_SEQ :
    8692                 :            :                                                 MLX5_FLOW_ACTION_DEC_TCP_SEQ;
    8693                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TCPSEQ;
    8694                 :          0 :                         break;
    8695                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
    8696                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
    8697                 :          0 :                         ret = flow_dv_validate_action_modify_tcp_ack
    8698                 :            :                                                                 (action_flags,
    8699                 :            :                                                                  actions,
    8700                 :            :                                                                  item_flags,
    8701                 :            :                                                                  error);
    8702         [ #  # ]:          0 :                         if (ret < 0)
    8703                 :          0 :                                 return ret;
    8704                 :            :                         /* Count all modify-header actions as one action. */
    8705         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8706                 :          0 :                                 ++actions_n;
    8707         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8708                 :            :                                 modify_after_mirror = 1;
    8709                 :          0 :                         action_flags |= actions->type ==
    8710                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
    8711         [ #  # ]:          0 :                                                 MLX5_FLOW_ACTION_INC_TCP_ACK :
    8712                 :            :                                                 MLX5_FLOW_ACTION_DEC_TCP_ACK;
    8713                 :          0 :                         rw_act_num += MLX5_ACT_NUM_MDF_TCPACK;
    8714                 :          0 :                         break;
    8715                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
    8716                 :            :                         break;
    8717                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
    8718                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
    8719                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8720                 :          0 :                         break;
    8721                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
    8722         [ #  # ]:          0 :                         if (priv->sh->config.dv_flow_en == 2)
    8723                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8724                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8725                 :            :                                                   actions,
    8726                 :            :                                                   "action not supported");
    8727                 :          0 :                         ret = mlx5_flow_validate_action_meter(dev,
    8728                 :            :                                                               action_flags,
    8729                 :            :                                                               item_flags,
    8730                 :            :                                                               actions, attr,
    8731                 :            :                                                               port_id_item,
    8732                 :            :                                                               &def_policy,
    8733                 :            :                                                               error);
    8734         [ #  # ]:          0 :                         if (ret < 0)
    8735                 :          0 :                                 return ret;
    8736                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
    8737         [ #  # ]:          0 :                         if (!def_policy)
    8738                 :          0 :                                 action_flags |=
    8739                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
    8740                 :          0 :                         ++actions_n;
    8741                 :            :                         /* Meter action will add one more TAG action. */
    8742                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_TAG;
    8743                 :          0 :                         break;
    8744                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
    8745         [ #  # ]:          0 :                         if (is_root)
    8746                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8747                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    8748                 :            :                                                                            NULL,
    8749                 :            :                           "Shared ASO age action is not supported for group 0");
    8750         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_AGE)
    8751                 :          0 :                                 return rte_flow_error_set
    8752                 :            :                                                   (error, EINVAL,
    8753                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION,
    8754                 :            :                                                    NULL,
    8755                 :            :                                                    "duplicate age actions set");
    8756         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8757                 :            :                                 aso_after_sample = 1;
    8758                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    8759                 :          0 :                         ++actions_n;
    8760                 :          0 :                         break;
    8761                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
    8762                 :          0 :                         non_shared_age = actions->conf;
    8763                 :          0 :                         ret = flow_dv_validate_action_age(action_flags,
    8764                 :            :                                                           actions, dev,
    8765                 :            :                                                           error);
    8766         [ #  # ]:          0 :                         if (ret < 0)
    8767                 :          0 :                                 return ret;
    8768                 :            :                         /*
    8769                 :            :                          * Validate the regular AGE action (using counter)
    8770                 :            :                          * mutual exclusion with indirect counter actions.
    8771                 :            :                          */
    8772         [ #  # ]:          0 :                         if (!flow_hit_aso_supported(priv, is_root)) {
    8773         [ #  # ]:          0 :                                 if (shared_count)
    8774                 :          0 :                                         return rte_flow_error_set
    8775                 :            :                                                 (error, EINVAL,
    8776                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8777                 :            :                                                 NULL,
    8778                 :            :                                                 "old age and indirect count combination is not supported");
    8779         [ #  # ]:          0 :                                 if (sample_count)
    8780                 :          0 :                                         return rte_flow_error_set
    8781                 :            :                                                 (error, EINVAL,
    8782                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    8783                 :            :                                                 NULL,
    8784                 :            :                                                 "old age action and count must be in the same sub flow");
    8785                 :            :                         } else {
    8786         [ #  # ]:          0 :                                 if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8787                 :            :                                         aso_after_sample = 1;
    8788                 :            :                         }
    8789                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
    8790                 :          0 :                         ++actions_n;
    8791                 :          0 :                         break;
    8792                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
    8793                 :          0 :                         ret = flow_dv_validate_action_modify_ipv4_dscp
    8794                 :            :                                                          (action_flags,
    8795                 :            :                                                           actions,
    8796                 :            :                                                           item_flags,
    8797                 :            :                                                           error);
    8798         [ #  # ]:          0 :                         if (ret < 0)
    8799                 :          0 :                                 return ret;
    8800                 :            :                         /* Count all modify-header actions as one action. */
    8801         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8802                 :          0 :                                 ++actions_n;
    8803         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8804                 :            :                                 modify_after_mirror = 1;
    8805                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
    8806                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_DSCP;
    8807                 :          0 :                         break;
    8808                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
    8809                 :          0 :                         ret = flow_dv_validate_action_modify_ipv6_dscp
    8810                 :            :                                                                 (action_flags,
    8811                 :            :                                                                  actions,
    8812                 :            :                                                                  item_flags,
    8813                 :            :                                                                  error);
    8814         [ #  # ]:          0 :                         if (ret < 0)
    8815                 :          0 :                                 return ret;
    8816                 :            :                         /* Count all modify-header actions as one action. */
    8817         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8818                 :          0 :                                 ++actions_n;
    8819         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8820                 :            :                                 modify_after_mirror = 1;
    8821                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
    8822                 :          0 :                         rw_act_num += MLX5_ACT_NUM_SET_DSCP;
    8823                 :          0 :                         break;
    8824                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
    8825                 :          0 :                         ret = flow_dv_validate_action_sample(&action_flags,
    8826                 :            :                                                              &sub_action_flags,
    8827                 :            :                                                              actions, dev,
    8828                 :            :                                                              attr, item_flags,
    8829                 :            :                                                              rss, &sample_rss,
    8830                 :            :                                                              &sample_count,
    8831                 :            :                                                              &fdb_mirror,
    8832                 :            :                                                              &sample_port_id,
    8833                 :            :                                                              is_root,
    8834                 :            :                                                              error);
    8835         [ #  # ]:          0 :                         if (ret < 0)
    8836                 :          0 :                                 return ret;
    8837   [ #  #  #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) &&
    8838                 :          0 :                             tag_id == 0 &&
    8839         [ #  # ]:          0 :                             priv->sh->registers.aso_reg == REG_NON)
    8840                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8841                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8842                 :            :                                         "sample after tag action causes metadata tag index 0 corruption");
    8843                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SAMPLE;
    8844                 :          0 :                         ++actions_n;
    8845                 :          0 :                         break;
    8846                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
    8847                 :          0 :                         ret = flow_dv_validate_action_modify_field(dev,
    8848                 :            :                                                                    action_flags,
    8849                 :            :                                                                    actions,
    8850                 :            :                                                                    attr,
    8851                 :            :                                                                    is_root,
    8852                 :            :                                                                    error);
    8853         [ #  # ]:          0 :                         if (ret < 0)
    8854                 :          0 :                                 return ret;
    8855         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8856                 :            :                                 modify_after_mirror = 1;
    8857                 :            :                         /* Count all modify-header actions as one action. */
    8858         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
    8859                 :          0 :                                 ++actions_n;
    8860                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
    8861                 :          0 :                         rw_act_num += ret;
    8862                 :          0 :                         break;
    8863                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
    8864                 :          0 :                         ret = mlx5_flow_dv_validate_action_aso_ct(dev,
    8865                 :            :                                                                   action_flags,
    8866                 :            :                                                                   item_flags,
    8867                 :            :                                                                   is_root,
    8868                 :            :                                                                   error);
    8869         [ #  # ]:          0 :                         if (ret < 0)
    8870                 :          0 :                                 return ret;
    8871         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
    8872                 :            :                                 aso_after_sample = 1;
    8873                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
    8874                 :          0 :                         break;
    8875                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET:
    8876                 :            :                         /* tunnel offload action was processed before
    8877                 :            :                          * list it here as a supported type
    8878                 :            :                          */
    8879                 :            :                         break;
    8880                 :            : #ifdef HAVE_MLX5DV_DR_ACTION_CREATE_DEST_ROOT_TABLE
    8881                 :            :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
    8882                 :            :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
    8883                 :            :                         ++actions_n;
    8884                 :            :                         break;
    8885                 :            : #endif
    8886                 :          0 :                 default:
    8887                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8888                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8889                 :            :                                                   actions,
    8890                 :            :                                                   "action not supported");
    8891                 :            :                 }
    8892                 :            :         }
    8893                 :            :         /*
    8894                 :            :          * Validate actions in flow rules
    8895                 :            :          * - Explicit decap action is prohibited by the tunnel offload API.
    8896                 :            :          * - Drop action in tunnel steer rule is prohibited by the API.
    8897                 :            :          * - Application cannot use MARK action because it's value can mask
    8898                 :            :          *   tunnel default miss notification.
    8899                 :            :          * - JUMP in tunnel match rule has no support in current PMD
    8900                 :            :          *   implementation.
    8901                 :            :          * - TAG & META are reserved for future uses.
    8902                 :            :          */
    8903         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_TUNNEL_SET) {
    8904                 :            :                 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_DECAP    |
    8905                 :            :                                             MLX5_FLOW_ACTION_MARK     |
    8906                 :            :                                             MLX5_FLOW_ACTION_SET_TAG  |
    8907                 :            :                                             MLX5_FLOW_ACTION_SET_META |
    8908                 :            :                                             MLX5_FLOW_ACTION_DROP;
    8909                 :            : 
    8910         [ #  # ]:          0 :                 if (action_flags & bad_actions_mask)
    8911                 :          0 :                         return rte_flow_error_set
    8912                 :            :                                         (error, EINVAL,
    8913                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8914                 :            :                                         "Invalid RTE action in tunnel "
    8915                 :            :                                         "set decap rule");
    8916         [ #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_ACTION_JUMP))
    8917                 :          0 :                         return rte_flow_error_set
    8918                 :            :                                         (error, EINVAL,
    8919                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8920                 :            :                                         "tunnel set decap rule must terminate "
    8921                 :            :                                         "with JUMP");
    8922         [ #  # ]:          0 :                 if (attr->egress)
    8923                 :          0 :                         return rte_flow_error_set
    8924                 :            :                                         (error, EINVAL,
    8925                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8926                 :            :                                         "tunnel flows for ingress and transfer traffic only");
    8927                 :            :         }
    8928         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_TUNNEL_MATCH) {
    8929                 :            :                 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_JUMP    |
    8930                 :            :                                             MLX5_FLOW_ACTION_MARK    |
    8931                 :            :                                             MLX5_FLOW_ACTION_SET_TAG |
    8932                 :            :                                             MLX5_FLOW_ACTION_SET_META;
    8933                 :            : 
    8934         [ #  # ]:          0 :                 if (action_flags & bad_actions_mask)
    8935                 :          0 :                         return rte_flow_error_set
    8936                 :            :                                         (error, EINVAL,
    8937                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8938                 :            :                                         "Invalid RTE action in tunnel "
    8939                 :            :                                         "set match rule");
    8940                 :            :         }
    8941                 :            :         /*
    8942                 :            :          * Validate the drop action mutual exclusion with other actions.
    8943                 :            :          * Drop action is mutually-exclusive with any other action, except for
    8944                 :            :          * Count/Sample/Age actions.
    8945                 :            :          * Drop action compatibility with tunnel offload was already validated.
    8946                 :            :          */
    8947         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_MATCH |
    8948                 :            :                             MLX5_FLOW_ACTION_TUNNEL_MATCH));
    8949         [ #  # ]:          0 :         else if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
    8950         [ #  # ]:          0 :             (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_DROP_INCLUSIVE_ACTIONS)))
    8951                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    8952                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    8953                 :            :                                           "Drop action is mutually-exclusive "
    8954                 :            :                                           "with any other action, except for "
    8955                 :            :                                           "Count/Sample/Age action");
    8956                 :            :         /* Eswitch has few restrictions on using items and actions */
    8957         [ #  # ]:          0 :         if (attr->transfer) {
    8958         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev) &&
    8959         [ #  # ]:          0 :                     action_flags & MLX5_FLOW_ACTION_FLAG)
    8960                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8961                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8962                 :            :                                                   NULL,
    8963                 :            :                                                   "unsupported action FLAG");
    8964         [ #  # ]:          0 :                 if (!mlx5_flow_ext_mreg_supported(dev) &&
    8965         [ #  # ]:          0 :                     action_flags & MLX5_FLOW_ACTION_MARK)
    8966                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    8967                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8968                 :            :                                                   NULL,
    8969                 :            :                                                   "unsupported action MARK");
    8970         [ #  # ]:          0 :                 if (!priv->jump_fdb_rx_en) {
    8971         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_QUEUE)
    8972                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8973                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    8974                 :            :                                                           NULL,
    8975                 :            :                                                           "unsupported action QUEUE");
    8976         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_RSS)
    8977                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    8978                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    8979                 :            :                                                           NULL,
    8980                 :            :                                                           "unsupported action RSS");
    8981         [ #  # ]:          0 :                         if (!(action_flags & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
    8982                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    8983                 :            :                                                           RTE_FLOW_ERROR_TYPE_ACTION,
    8984                 :            :                                                           actions,
    8985                 :            :                                                           "no fate action is found");
    8986                 :            :                 }
    8987                 :            :         } else {
    8988   [ #  #  #  # ]:          0 :                 if (!(action_flags & MLX5_FLOW_FATE_ACTIONS) && attr->ingress)
    8989                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    8990                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    8991                 :            :                                                   actions,
    8992                 :            :                                                   "no fate action is found");
    8993                 :            :         }
    8994                 :            :         /*
    8995                 :            :          * Continue validation for Xcap and VLAN actions.
    8996                 :            :          * If hairpin is working in explicit TX rule mode, there is no actions
    8997                 :            :          * splitting and the validation of hairpin ingress flow should be the
    8998                 :            :          * same as other standard flows.
    8999                 :            :          */
    9000         [ #  # ]:          0 :         if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS |
    9001         [ #  # ]:          0 :                              MLX5_FLOW_VLAN_ACTIONS)) &&
    9002   [ #  #  #  # ]:          0 :             (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index) ||
    9003                 :          0 :              ((conf = mlx5_rxq_get_hairpin_conf(dev, queue_index)) != NULL &&
    9004         [ #  # ]:          0 :              conf->tx_explicit != 0))) {
    9005         [ #  # ]:          0 :                 if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
    9006                 :            :                     MLX5_FLOW_XCAP_ACTIONS)
    9007                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    9008                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
    9009                 :            :                                                   NULL, "encap and decap "
    9010                 :            :                                                   "combination aren't supported");
    9011                 :            :                 /* Push VLAN is not supported in ingress except for NICs newer than CX5. */
    9012         [ #  # ]:          0 :                 if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) {
    9013                 :          0 :                         struct mlx5_dev_ctx_shared *sh = priv->sh;
    9014                 :            :                         bool direction_error = false;
    9015                 :            : 
    9016         [ #  # ]:          0 :                         if (attr->transfer) {
    9017         [ #  # ]:          0 :                                 bool fdb_tx = flow_source_vport_representor(priv, act_priv);
    9018                 :          0 :                                 bool is_cx5 = sh->steering_format_version ==
    9019                 :            :                                     MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
    9020                 :            : 
    9021         [ #  # ]:          0 :                                 if (!fdb_tx && is_cx5)
    9022                 :            :                                         direction_error = true;
    9023         [ #  # ]:          0 :                         } else if (attr->ingress) {
    9024                 :            :                                 direction_error = true;
    9025                 :            :                         }
    9026                 :            :                         if (direction_error)
    9027                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    9028                 :            :                                                           RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
    9029                 :            :                                                           NULL,
    9030                 :            :                                                           "push VLAN action not supported "
    9031                 :            :                                                           "for ingress");
    9032                 :            :                 }
    9033         [ #  # ]:          0 :                 if (attr->ingress) {
    9034         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    9035                 :          0 :                                 return rte_flow_error_set
    9036                 :            :                                                 (error, ENOTSUP,
    9037                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
    9038                 :            :                                                  NULL, "encap is not supported"
    9039                 :            :                                                  " for ingress traffic");
    9040         [ #  # ]:          0 :                         else if ((action_flags & MLX5_FLOW_VLAN_ACTIONS) ==
    9041                 :            :                                         MLX5_FLOW_VLAN_ACTIONS)
    9042                 :          0 :                                 return rte_flow_error_set
    9043                 :            :                                                 (error, ENOTSUP,
    9044                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
    9045                 :            :                                                  NULL, "no support for "
    9046                 :            :                                                  "multiple VLAN actions");
    9047                 :            :                 }
    9048                 :            :         }
    9049                 :            :         /* Pop VLAN is not supported in egress except for NICs newer than CX5. */
    9050         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_OF_POP_VLAN) {
    9051                 :          0 :                 struct mlx5_dev_ctx_shared *sh = priv->sh;
    9052                 :            :                 bool direction_error = false;
    9053                 :            : 
    9054         [ #  # ]:          0 :                 if (attr->transfer) {
    9055         [ #  # ]:          0 :                         bool fdb_tx = flow_source_vport_representor(priv, act_priv);
    9056                 :          0 :                         bool is_cx5 = sh->steering_format_version ==
    9057                 :            :                                         MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
    9058                 :            : 
    9059         [ #  # ]:          0 :                         if (fdb_tx && is_cx5)
    9060                 :            :                                 direction_error = true;
    9061         [ #  # ]:          0 :                 } else if (attr->egress) {
    9062                 :            :                         direction_error = true;
    9063                 :            :                 }
    9064                 :            :                 if (direction_error)
    9065                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    9066                 :            :                                                 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
    9067                 :            :                                                 NULL,
    9068                 :            :                                                 "pop vlan action not supported for egress");
    9069                 :            :         }
    9070         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY) {
    9071         [ #  # ]:          0 :                 if ((action_flags & (MLX5_FLOW_FATE_ACTIONS &
    9072         [ #  # ]:          0 :                         ~MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)) &&
    9073                 :            :                         attr->ingress)
    9074                 :          0 :                         return rte_flow_error_set
    9075                 :            :                                 (error, ENOTSUP,
    9076                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION,
    9077                 :            :                                 NULL, "fate action not supported for "
    9078                 :            :                                 "meter with policy");
    9079         [ #  # ]:          0 :                 if (attr->egress) {
    9080         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)
    9081                 :          0 :                                 return rte_flow_error_set
    9082                 :            :                                         (error, ENOTSUP,
    9083                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9084                 :            :                                         NULL, "modify header action in egress "
    9085                 :            :                                         "cannot be done before meter action");
    9086         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_ENCAP)
    9087                 :          0 :                                 return rte_flow_error_set
    9088                 :            :                                         (error, ENOTSUP,
    9089                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9090                 :            :                                         NULL, "encap action in egress "
    9091                 :            :                                         "cannot be done before meter action");
    9092         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
    9093                 :          0 :                                 return rte_flow_error_set
    9094                 :            :                                         (error, ENOTSUP,
    9095                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
    9096                 :            :                                         NULL, "push vlan action in egress "
    9097                 :            :                                         "cannot be done before meter action");
    9098                 :            :                 }
    9099                 :            :         }
    9100                 :            :         /*
    9101                 :            :          * Only support one ASO action in a single flow rule.
    9102                 :            :          * non-shared AGE + counter will fallback to use HW counter, no ASO hit object.
    9103                 :            :          * Group 0 uses HW counter for AGE too even if no counter action.
    9104                 :            :          */
    9105   [ #  #  #  # ]:          0 :         aso_mask = (action_flags & MLX5_FLOW_ACTION_METER && priv->sh->meter_aso_en) << 2 |
    9106   [ #  #  #  #  :          0 :                    (action_flags & MLX5_FLOW_ACTION_CT && priv->sh->ct_aso_en) << 1 |
                   #  # ]
    9107                 :          0 :                    (action_flags & MLX5_FLOW_ACTION_AGE &&
    9108         [ #  # ]:          0 :                     !(non_shared_age && count) &&
    9109   [ #  #  #  #  :          0 :                     (attr->group || (attr->transfer && priv->fdb_def_rule)) &&
             #  #  #  # ]
    9110         [ #  # ]:          0 :                     priv->sh->flow_hit_aso_en);
    9111         [ #  # ]:          0 :         if (rte_popcount64(aso_mask) > 1)
    9112                 :          0 :                 return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
    9113                 :            :                                           NULL, "unsupported combining AGE, METER, CT ASO actions in a single rule");
    9114                 :            :         /*
    9115                 :            :          * Hairpin flow will add one more TAG action in TX implicit mode.
    9116                 :            :          * In TX explicit mode, there will be no hairpin flow ID.
    9117                 :            :          */
    9118         [ #  # ]:          0 :         if (hairpin > 0)
    9119                 :          0 :                 rw_act_num += MLX5_ACT_NUM_SET_TAG;
    9120                 :            :         /* extra metadata enabled: one more TAG action will be add. */
    9121         [ #  # ]:          0 :         if (dev_conf->dv_flow_en &&
    9122   [ #  #  #  # ]:          0 :             dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
    9123                 :          0 :             mlx5_flow_ext_mreg_supported(dev))
    9124                 :          0 :                 rw_act_num += MLX5_ACT_NUM_SET_TAG;
    9125         [ #  # ]:          0 :         if (rw_act_num >
    9126                 :            :                         flow_dv_modify_hdr_action_max(dev, is_root)) {
    9127                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    9128                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
    9129                 :            :                                           NULL, "too many header modify"
    9130                 :            :                                           " actions to support");
    9131                 :            :         }
    9132         [ #  # ]:          0 :         if (fdb_mirror) {
    9133   [ #  #  #  # ]:          0 :                 if (!priv->sh->cdev->config.hca_attr.reg_c_preserve &&
    9134         [ #  # ]:          0 :                     flow_source_vport_representor(priv, act_priv)) {
    9135                 :            :                         /* Eswitch egress mirror and modify flow has limitation on CX5 */
    9136         [ #  # ]:          0 :                         if (modify_after_mirror)
    9137                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    9138                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9139                 :            :                                                 "sample before modify action is not supported");
    9140         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_JUMP)
    9141                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    9142                 :            :                                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9143                 :            :                                                         "sample and jump action combination is not supported");
    9144                 :            :                 }
    9145         [ #  # ]:          0 :                 if (aso_mask > 0 && aso_after_sample && fdb_mirror)
    9146                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    9147                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9148                 :            :                                                   "sample before ASO action is not supported");
    9149         [ #  # ]:          0 :                 if (sub_action_flags & MLX5_FLOW_ACTION_PORT_ID) {
    9150                 :          0 :                         port_priv = mlx5_port_to_eswitch_info(sample_port_id, false);
    9151         [ #  # ]:          0 :                         if (flow_source_vport_representor(priv, port_priv)) {
    9152         [ #  # ]:          0 :                                 if (sub_action_flags & MLX5_FLOW_ACTION_ENCAP)
    9153                 :          0 :                                         return rte_flow_error_set(error, ENOTSUP,
    9154                 :            :                                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9155                 :            :                                                                 "mirror to rep port with encap is not supported");
    9156                 :            :                         } else {
    9157         [ #  # ]:          0 :                                 if (!(sub_action_flags & MLX5_FLOW_ACTION_ENCAP) &&
    9158         [ #  # ]:          0 :                                     (action_flags & MLX5_FLOW_ACTION_JUMP))
    9159                 :          0 :                                         return rte_flow_error_set(error, ENOTSUP,
    9160                 :            :                                                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9161                 :            :                                                                 "mirror to wire port without encap is not supported");
    9162                 :            :                         }
    9163                 :            :                 }
    9164         [ #  # ]:          0 :                 if ((action_flags & MLX5_FLOW_ACTION_PORT_ID) &&
    9165                 :            :                     (action_flags & MLX5_FLOW_ACTION_ENCAP)) {
    9166                 :          0 :                         port_priv = mlx5_port_to_eswitch_info(port_id, false);
    9167         [ #  # ]:          0 :                         if (flow_source_vport_representor(priv, port_priv))
    9168                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    9169                 :            :                                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    9170                 :            :                                                         "mirror to rep port with encap is not supported");
    9171                 :            :                 }
    9172                 :            :         }
    9173                 :            :         /*
    9174                 :            :          * Validation the NIC Egress flow on representor, except implicit
    9175                 :            :          * hairpin default egress flow with TX_QUEUE item, other flows not
    9176                 :            :          * work due to metadata regC0 mismatch.
    9177                 :            :          */
    9178   [ #  #  #  #  :          0 :         if (attr->egress && priv->representor && !(item_flags & MLX5_FLOW_ITEM_SQ))
                   #  # ]
    9179                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    9180                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    9181                 :            :                                           NULL,
    9182                 :            :                                           "NIC egress rules on representors"
    9183                 :            :                                           " is not supported");
    9184                 :            :         return 0;
    9185                 :            : }
    9186                 :            : 
    9187                 :            : /**
    9188                 :            :  * Internal preparation function. Allocates the DV flow size,
    9189                 :            :  * this size is constant.
    9190                 :            :  *
    9191                 :            :  * @param[in] dev
    9192                 :            :  *   Pointer to the rte_eth_dev structure.
    9193                 :            :  * @param[in] attr
    9194                 :            :  *   Pointer to the flow attributes.
    9195                 :            :  * @param[in] items
    9196                 :            :  *   Pointer to the list of items.
    9197                 :            :  * @param[in] actions
    9198                 :            :  *   Pointer to the list of actions.
    9199                 :            :  * @param[out] error
    9200                 :            :  *   Pointer to the error structure.
    9201                 :            :  *
    9202                 :            :  * @return
    9203                 :            :  *   Pointer to mlx5_flow object on success,
    9204                 :            :  *   otherwise NULL and rte_errno is set.
    9205                 :            :  */
    9206                 :            : static struct mlx5_flow *
    9207                 :          0 : flow_dv_prepare(struct rte_eth_dev *dev,
    9208                 :            :                 const struct rte_flow_attr *attr __rte_unused,
    9209                 :            :                 const struct rte_flow_item items[] __rte_unused,
    9210                 :            :                 const struct rte_flow_action actions[] __rte_unused,
    9211                 :            :                 struct rte_flow_error *error)
    9212                 :            : {
    9213                 :          0 :         uint32_t handle_idx = 0;
    9214                 :            :         struct mlx5_flow *dev_flow;
    9215                 :            :         struct mlx5_flow_handle *dev_handle;
    9216                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    9217                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
    9218                 :            : 
    9219                 :            :         MLX5_ASSERT(wks);
    9220                 :          0 :         wks->skip_matcher_reg = 0;
    9221                 :          0 :         wks->policy = NULL;
    9222                 :          0 :         wks->final_policy = NULL;
    9223                 :          0 :         wks->vport_meta_tag = 0;
    9224                 :            :         /* In case of corrupting the memory. */
    9225         [ #  # ]:          0 :         if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) {
    9226                 :          0 :                 rte_flow_error_set(error, ENOSPC,
    9227                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9228                 :            :                                    "not free temporary device flow");
    9229                 :          0 :                 return NULL;
    9230                 :            :         }
    9231                 :          0 :         dev_handle = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
    9232                 :            :                                    &handle_idx);
    9233         [ #  # ]:          0 :         if (!dev_handle) {
    9234                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    9235                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    9236                 :            :                                    "not enough memory to create flow handle");
    9237                 :          0 :                 return NULL;
    9238                 :            :         }
    9239                 :            :         MLX5_ASSERT(wks->flow_idx < RTE_DIM(wks->flows));
    9240                 :          0 :         dev_flow = &wks->flows[wks->flow_idx++];
    9241                 :            :         memset(dev_flow, 0, sizeof(*dev_flow));
    9242                 :          0 :         dev_flow->handle = dev_handle;
    9243                 :          0 :         dev_flow->handle_idx = handle_idx;
    9244                 :          0 :         dev_flow->dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);
    9245                 :          0 :         dev_flow->ingress = attr->ingress;
    9246                 :          0 :         dev_flow->dv.transfer = attr->transfer;
    9247                 :          0 :         return dev_flow;
    9248                 :            : }
    9249                 :            : 
    9250                 :            : #ifdef RTE_PMD_MLX5_DEBUG
    9251                 :            : /**
    9252                 :            :  * Sanity check for match mask and value. Similar to check_valid_spec() in
    9253                 :            :  * kernel driver. If unmasked bit is present in value, it returns failure.
    9254                 :            :  *
    9255                 :            :  * @param match_mask
    9256                 :            :  *   pointer to match mask buffer.
    9257                 :            :  * @param match_value
    9258                 :            :  *   pointer to match value buffer.
    9259                 :            :  *
    9260                 :            :  * @return
    9261                 :            :  *   0 if valid, -EINVAL otherwise.
    9262                 :            :  */
    9263                 :            : static int
    9264                 :            : flow_dv_check_valid_spec(void *match_mask, void *match_value)
    9265                 :            : {
    9266                 :            :         uint8_t *m = match_mask;
    9267                 :            :         uint8_t *v = match_value;
    9268                 :            :         unsigned int i;
    9269                 :            : 
    9270                 :            :         for (i = 0; i < MLX5_ST_SZ_BYTES(fte_match_param); ++i) {
    9271                 :            :                 if (v[i] & ~m[i]) {
    9272                 :            :                         DRV_LOG(ERR,
    9273                 :            :                                 "match_value differs from match_criteria"
    9274                 :            :                                 " %p[%u] != %p[%u]",
    9275                 :            :                                 match_value, i, match_mask, i);
    9276                 :            :                         return -EINVAL;
    9277                 :            :                 }
    9278                 :            :         }
    9279                 :            :         return 0;
    9280                 :            : }
    9281                 :            : #endif
    9282                 :            : 
    9283                 :            : /**
    9284                 :            :  * Add match of ip_version.
    9285                 :            :  *
    9286                 :            :  * @param[in] group
    9287                 :            :  *   Flow group.
    9288                 :            :  * @param[in] headers_v
    9289                 :            :  *   Values header pointer.
    9290                 :            :  * @param[in] headers_m
    9291                 :            :  *   Masks header pointer.
    9292                 :            :  * @param[in] ip_version
    9293                 :            :  *   The IP version to set.
    9294                 :            :  */
    9295                 :            : static inline void
    9296                 :          0 : flow_dv_set_match_ip_version(uint32_t group,
    9297                 :            :                              void *headers_v,
    9298                 :            :                              uint32_t key_type,
    9299                 :            :                              uint8_t ip_version)
    9300                 :            : {
    9301   [ #  #  #  # ]:          0 :         if (group == 0 && (key_type & MLX5_SET_MATCHER_M))
    9302         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 0xf);
    9303                 :            :         else
    9304         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version,
    9305                 :            :                          ip_version);
    9306         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, 0);
    9307                 :          0 : }
    9308                 :            : 
    9309                 :            : /**
    9310                 :            :  * Add Ethernet item to the value.
    9311                 :            :  *
    9312                 :            :  * @param[in, out] key
    9313                 :            :  *   Flow matcher value.
    9314                 :            :  * @param[in] item
    9315                 :            :  *   Flow pattern to translate.
    9316                 :            :  * @param[in] inner
    9317                 :            :  *   Item is inner pattern.
    9318                 :            :  * @param[in] grpup
    9319                 :            :  *   Flow matcher group.
    9320                 :            :  * @param[in] key_type
    9321                 :            :  *   Set flow matcher mask or value.
    9322                 :            :  */
    9323                 :            : static void
    9324                 :          0 : flow_dv_translate_item_eth(void *key, const struct rte_flow_item *item,
    9325                 :            :                            int inner, uint32_t group, uint32_t key_type)
    9326                 :            : {
    9327                 :          0 :         const struct rte_flow_item_eth *eth_vv = item->spec;
    9328                 :            :         const struct rte_flow_item_eth *eth_m;
    9329                 :            :         const struct rte_flow_item_eth *eth_v;
    9330                 :          0 :         const struct rte_flow_item_eth nic_mask = {
    9331                 :            :                 .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    9332                 :            :                 .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    9333                 :            :                 .hdr.ether_type = RTE_BE16(0xffff),
    9334                 :            :                 .has_vlan = 0,
    9335                 :            :         };
    9336                 :            :         void *hdrs_v;
    9337                 :            :         char *l24_v;
    9338                 :            :         unsigned int i;
    9339                 :            : 
    9340   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9341                 :          0 :                 return;
    9342   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, eth_v, eth_m, &nic_mask);
             #  #  #  # ]
    9343         [ #  # ]:          0 :         if (!eth_vv)
    9344                 :            :                 eth_vv = eth_v;
    9345         [ #  # ]:          0 :         if (inner)
    9346                 :          0 :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
    9347                 :            :         else
    9348                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9349                 :            :         /* The value must be in the range of the mask. */
    9350                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, dmac_47_16);
    9351         [ #  # ]:          0 :         for (i = 0; i < sizeof(eth_m->hdr.dst_addr); ++i)
    9352                 :          0 :                 l24_v[i] = eth_m->hdr.dst_addr.addr_bytes[i] & eth_v->hdr.dst_addr.addr_bytes[i];
    9353                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, smac_47_16);
    9354                 :            :         /* The value must be in the range of the mask. */
    9355         [ #  # ]:          0 :         for (i = 0; i < sizeof(eth_m->hdr.dst_addr); ++i)
    9356                 :          0 :                 l24_v[i] = eth_m->hdr.src_addr.addr_bytes[i] & eth_v->hdr.src_addr.addr_bytes[i];
    9357                 :            :         /*
    9358                 :            :          * HW supports match on one Ethertype, the Ethertype following the last
    9359                 :            :          * VLAN tag of the packet (see PRM).
    9360                 :            :          * Set match on ethertype only if ETH header is not followed by VLAN.
    9361                 :            :          * HW is optimized for IPv4/IPv6. In such cases, avoid setting
    9362                 :            :          * ethertype, and use ip_version field instead.
    9363                 :            :          * eCPRI over Ether layer will use type value 0xAEFE.
    9364                 :            :          */
    9365         [ #  # ]:          0 :         if (eth_m->hdr.ether_type == 0xFFFF) {
    9366                 :          0 :                 rte_be16_t type = eth_v->hdr.ether_type;
    9367                 :            : 
    9368                 :            :                 /*
    9369                 :            :                  * When set the matcher mask, refer to the original spec
    9370                 :            :                  * value.
    9371                 :            :                  */
    9372         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M) {
    9373         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9374                 :          0 :                         type = eth_vv->hdr.ether_type;
    9375                 :            :                 }
    9376                 :            :                 /* Set cvlan_tag mask for any single\multi\un-tagged case. */
    9377   [ #  #  #  #  :          0 :                 switch (type) {
                      # ]
    9378                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_VLAN):
    9379         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9380                 :          0 :                         return;
    9381                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_QINQ):
    9382         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9383                 :          0 :                         return;
    9384                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV4):
    9385                 :          0 :                         flow_dv_set_match_ip_version(group, hdrs_v, key_type,
    9386                 :            :                                                      4);
    9387                 :          0 :                         return;
    9388                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV6):
    9389                 :          0 :                         flow_dv_set_match_ip_version(group, hdrs_v, key_type,
    9390                 :            :                                                      6);
    9391                 :          0 :                         return;
    9392                 :            :                 default:
    9393                 :            :                         break;
    9394                 :            :                 }
    9395                 :            :         }
    9396                 :            :         /*
    9397                 :            :          * Only SW steering value should refer to the mask value.
    9398                 :            :          * Other cases are using the fake masks, just ignore the mask.
    9399                 :            :          */
    9400   [ #  #  #  # ]:          0 :         if (eth_v->has_vlan && eth_m->has_vlan) {
    9401                 :            :                 /*
    9402                 :            :                  * Here, when also has_more_vlan field in VLAN item is
    9403                 :            :                  * not set, only single-tagged packets will be matched.
    9404                 :            :                  */
    9405         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9406   [ #  #  #  # ]:          0 :                 if (key_type != MLX5_SET_MATCHER_HS_M && eth_vv->has_vlan)
    9407                 :            :                         return;
    9408                 :            :         }
    9409                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
    9410                 :          0 :         *(uint16_t *)(l24_v) = eth_m->hdr.ether_type & eth_v->hdr.ether_type;
    9411                 :            : }
    9412                 :            : 
    9413                 :            : /**
    9414                 :            :  * Add VLAN item to the value.
    9415                 :            :  *
    9416                 :            :  * @param[in, out] key
    9417                 :            :  *   Flow matcher value.
    9418                 :            :  * @param[in] item
    9419                 :            :  *   Flow pattern to translate.
    9420                 :            :  * @param[in] inner
    9421                 :            :  *   Item is inner pattern.
    9422                 :            :  * @param[in] wks
    9423                 :            :  *   Item workspace.
    9424                 :            :  * @param[in] key_type
    9425                 :            :  *   Set flow matcher mask or value.
    9426                 :            :  */
    9427                 :            : static void
    9428                 :          0 : flow_dv_translate_item_vlan(void *key, const struct rte_flow_item *item,
    9429                 :            :                             int inner, struct mlx5_dv_matcher_workspace *wks,
    9430                 :            :                             uint32_t key_type)
    9431                 :            : {
    9432                 :            :         const struct rte_flow_item_vlan *vlan_m;
    9433                 :            :         const struct rte_flow_item_vlan *vlan_v;
    9434                 :          0 :         const struct rte_flow_item_vlan *vlan_vv = item->spec;
    9435                 :            :         void *hdrs_v;
    9436                 :            :         uint16_t tci_v;
    9437                 :            : 
    9438         [ #  # ]:          0 :         if (inner) {
    9439                 :          0 :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
    9440                 :            :         } else {
    9441                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9442                 :            :                 /*
    9443                 :            :                  * This is workaround, masks are not supported,
    9444                 :            :                  * and pre-validated.
    9445                 :            :                  */
    9446         [ #  # ]:          0 :                 if (vlan_vv)
    9447         [ #  # ]:          0 :                         wks->vlan_tag = rte_be_to_cpu_16(vlan_vv->hdr.vlan_tci) & 0x0fff;
    9448                 :            :         }
    9449                 :            :         /*
    9450                 :            :          * When VLAN item exists in flow, mark packet as tagged,
    9451                 :            :          * even if TCI is not specified.
    9452                 :            :          */
    9453   [ #  #  #  # ]:          0 :         if (!MLX5_GET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag))
    9454         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
    9455   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9456                 :            :                 return;
    9457   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, vlan_v, vlan_m,
             #  #  #  # ]
    9458                 :            :                          &rte_flow_item_vlan_mask);
    9459         [ #  # ]:          0 :         tci_v = rte_be_to_cpu_16(vlan_m->hdr.vlan_tci & vlan_v->hdr.vlan_tci);
    9460         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_vid, tci_v);
    9461         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_cfi, tci_v >> 12);
    9462         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_prio, tci_v >> 13);
    9463                 :            :         /*
    9464                 :            :          * HW is optimized for IPv4/IPv6. In such cases, avoid setting
    9465                 :            :          * ethertype, and use ip_version field instead.
    9466                 :            :          */
    9467         [ #  # ]:          0 :         if (vlan_m->hdr.eth_proto == 0xFFFF) {
    9468                 :          0 :                 rte_be16_t inner_type = vlan_v->hdr.eth_proto;
    9469                 :            : 
    9470                 :            :                 /*
    9471                 :            :                  * When set the matcher mask, refer to the original spec
    9472                 :            :                  * value.
    9473                 :            :                  */
    9474         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M)
    9475                 :          0 :                         inner_type = vlan_vv->hdr.eth_proto;
    9476   [ #  #  #  # ]:          0 :                 switch (inner_type) {
    9477                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_VLAN):
    9478         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9479         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_V)
    9480         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
    9481                 :            :                                          cvlan_tag, 0);
    9482                 :          0 :                         return;
    9483                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV4):
    9484                 :          0 :                         flow_dv_set_match_ip_version
    9485                 :            :                                 (wks->group, hdrs_v, key_type, 4);
    9486                 :          0 :                         return;
    9487                 :          0 :                 case RTE_BE16(RTE_ETHER_TYPE_IPV6):
    9488                 :          0 :                         flow_dv_set_match_ip_version
    9489                 :            :                                 (wks->group, hdrs_v, key_type, 6);
    9490                 :          0 :                         return;
    9491                 :            :                 default:
    9492                 :            :                         break;
    9493                 :            :                 }
    9494                 :            :         }
    9495   [ #  #  #  # ]:          0 :         if (vlan_m->has_more_vlan && vlan_v->has_more_vlan) {
    9496         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
    9497                 :            :                 /* Only one vlan_tag bit can be set. */
    9498         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_V)
    9499         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0);
    9500                 :          0 :                 return;
    9501                 :            :         }
    9502   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, ethertype,
    9503                 :            :                  rte_be_to_cpu_16(vlan_m->hdr.eth_proto & vlan_v->hdr.eth_proto));
    9504                 :            : }
    9505                 :            : 
    9506                 :            : /**
    9507                 :            :  * Add IPV4 item to the value.
    9508                 :            :  *
    9509                 :            :  * @param[in, out] key
    9510                 :            :  *   Flow matcher value.
    9511                 :            :  * @param[in] item
    9512                 :            :  *   Flow pattern to translate.
    9513                 :            :  * @param[in] inner
    9514                 :            :  *   Item is inner pattern.
    9515                 :            :  * @param[in] group
    9516                 :            :  *   The group to insert the rule.
    9517                 :            :  * @param[in] key_type
    9518                 :            :  *   Set flow matcher mask or value.
    9519                 :            :  */
    9520                 :            : static void
    9521                 :          0 : flow_dv_translate_item_ipv4(void *key, const struct rte_flow_item *item,
    9522                 :            :                             int inner, uint32_t group, uint32_t key_type)
    9523                 :            : {
    9524                 :            :         const struct rte_flow_item_ipv4 *ipv4_m;
    9525                 :            :         const struct rte_flow_item_ipv4 *ipv4_v;
    9526                 :          0 :         const struct rte_flow_item_ipv4 nic_mask = {
    9527                 :            :                 .hdr = {
    9528                 :            :                         .src_addr = RTE_BE32(0xffffffff),
    9529                 :            :                         .dst_addr = RTE_BE32(0xffffffff),
    9530                 :            :                         .type_of_service = 0xff,
    9531                 :            :                         .next_proto_id = 0xff,
    9532                 :            :                         .time_to_live = 0xff,
    9533                 :            :                 },
    9534                 :            :         };
    9535                 :            :         void *headers_v;
    9536                 :            :         char *l24_v;
    9537                 :            :         uint8_t tos;
    9538                 :            : 
    9539         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9540                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9541                 :          0 :         flow_dv_set_match_ip_version(group, headers_v, key_type, 4);
    9542   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9543                 :          0 :                 return;
    9544   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv4_v, ipv4_m, &nic_mask);
             #  #  #  # ]
    9545                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9546                 :            :                              dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
    9547                 :          0 :         *(uint32_t *)l24_v = ipv4_m->hdr.dst_addr & ipv4_v->hdr.dst_addr;
    9548                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9549                 :            :                           src_ipv4_src_ipv6.ipv4_layout.ipv4);
    9550                 :          0 :         *(uint32_t *)l24_v = ipv4_m->hdr.src_addr & ipv4_v->hdr.src_addr;
    9551                 :          0 :         tos = ipv4_m->hdr.type_of_service & ipv4_v->hdr.type_of_service;
    9552         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ipv4_ihl,
    9553                 :            :                  ipv4_v->hdr.ihl & ipv4_m->hdr.ihl);
    9554         [ #  # ]:          0 :         if (key_type == MLX5_SET_MATCHER_SW_M)
    9555         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
    9556                 :            :                          ipv4_v->hdr.type_of_service);
    9557         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, tos);
    9558         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, tos >> 2);
    9559         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9560                 :            :                  ipv4_v->hdr.next_proto_id & ipv4_m->hdr.next_proto_id);
    9561         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit,
    9562                 :            :                  ipv4_v->hdr.time_to_live & ipv4_m->hdr.time_to_live);
    9563         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
    9564                 :            :                  !!(ipv4_v->hdr.fragment_offset & ipv4_m->hdr.fragment_offset));
    9565                 :            : }
    9566                 :            : 
    9567                 :            : /**
    9568                 :            :  * Add IPV6 item to the value.
    9569                 :            :  *
    9570                 :            :  * @param[in, out] key
    9571                 :            :  *   Flow matcher value.
    9572                 :            :  * @param[in] item
    9573                 :            :  *   Flow pattern to translate.
    9574                 :            :  * @param[in] inner
    9575                 :            :  *   Item is inner pattern.
    9576                 :            :  * @param[in] group
    9577                 :            :  *   The group to insert the rule.
    9578                 :            :  * @param[in] key_type
    9579                 :            :  *   Set flow matcher mask or value.
    9580                 :            :  */
    9581                 :            : static void
    9582                 :          0 : flow_dv_translate_item_ipv6(void *key, const struct rte_flow_item *item,
    9583                 :            :                             int inner, uint32_t group, uint32_t key_type)
    9584                 :            : {
    9585                 :            :         const struct rte_flow_item_ipv6 *ipv6_m;
    9586                 :            :         const struct rte_flow_item_ipv6 *ipv6_v;
    9587                 :          0 :         const struct rte_flow_item_ipv6 nic_mask = {
    9588                 :            :                 .hdr = {
    9589                 :            :                         .src_addr = RTE_IPV6_MASK_FULL,
    9590                 :            :                         .dst_addr = RTE_IPV6_MASK_FULL,
    9591                 :            :                         .vtc_flow = RTE_BE32(0xffffffff),
    9592                 :            :                         .proto = 0xff,
    9593                 :            :                         .hop_limits = 0xff,
    9594                 :            :                 },
    9595                 :            :         };
    9596                 :            :         void *headers_v;
    9597                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9598                 :            :         char *l24_v;
    9599                 :            :         uint32_t vtc_v;
    9600                 :            :         int i;
    9601                 :            :         int size;
    9602                 :            : 
    9603         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9604                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9605                 :          0 :         flow_dv_set_match_ip_version(group, headers_v, key_type, 6);
    9606   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9607                 :          0 :                 return;
    9608   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv6_v, ipv6_m, &nic_mask);
             #  #  #  # ]
    9609                 :            :         size = sizeof(ipv6_m->hdr.dst_addr);
    9610                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9611                 :            :                              dst_ipv4_dst_ipv6.ipv6_layout.ipv6);
    9612         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9613                 :          0 :                 l24_v[i] = ipv6_m->hdr.dst_addr.a[i] & ipv6_v->hdr.dst_addr.a[i];
    9614                 :            :         l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
    9615                 :            :                              src_ipv4_src_ipv6.ipv6_layout.ipv6);
    9616         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
    9617                 :          0 :                 l24_v[i] = ipv6_m->hdr.src_addr.a[i] & ipv6_v->hdr.src_addr.a[i];
    9618                 :            :         /* TOS. */
    9619         [ #  # ]:          0 :         vtc_v = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow & ipv6_v->hdr.vtc_flow);
    9620         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, vtc_v >> 20);
    9621         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, vtc_v >> 22);
    9622                 :            :         /* Label. */
    9623         [ #  # ]:          0 :         if (inner)
    9624         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc, misc_v, inner_ipv6_flow_label,
    9625                 :            :                          vtc_v);
    9626                 :            :         else
    9627         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc, misc_v, outer_ipv6_flow_label,
    9628                 :            :                          vtc_v);
    9629                 :            :         /* Protocol. */
    9630         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9631                 :            :                  ipv6_v->hdr.proto & ipv6_m->hdr.proto);
    9632                 :            :         /* Hop limit. */
    9633         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit,
    9634                 :            :                  ipv6_v->hdr.hop_limits & ipv6_m->hdr.hop_limits);
    9635         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
    9636                 :            :                  !!(ipv6_v->has_frag_ext & ipv6_m->has_frag_ext));
    9637                 :            : }
    9638                 :            : 
    9639                 :            : /**
    9640                 :            :  * Add IPV6 fragment extension item to the value.
    9641                 :            :  *
    9642                 :            :  * @param[in, out] key
    9643                 :            :  *   Flow matcher value.
    9644                 :            :  * @param[in] item
    9645                 :            :  *   Flow pattern to translate.
    9646                 :            :  * @param[in] inner
    9647                 :            :  *   Item is inner pattern.
    9648                 :            :  * @param[in] key_type
    9649                 :            :  *   Set flow matcher mask or value.
    9650                 :            :  */
    9651                 :            : static void
    9652                 :          0 : flow_dv_translate_item_ipv6_frag_ext(void *key,
    9653                 :            :                                      const struct rte_flow_item *item,
    9654                 :            :                                      int inner, uint32_t key_type)
    9655                 :            : {
    9656                 :            :         const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_m;
    9657                 :            :         const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_v;
    9658                 :          0 :         const struct rte_flow_item_ipv6_frag_ext nic_mask = {
    9659                 :            :                 .hdr = {
    9660                 :            :                         .next_header = 0xff,
    9661                 :            :                         .frag_data = RTE_BE16(0xffff),
    9662                 :            :                 },
    9663                 :            :         };
    9664                 :            :         void *headers_v;
    9665                 :            : 
    9666         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9667                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9668                 :            :         /* IPv6 fragment extension item exists, so packet is IP fragment. */
    9669         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 1);
    9670   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9671                 :          0 :                 return;
    9672   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ipv6_frag_ext_v,
             #  #  #  # ]
    9673                 :            :                          ipv6_frag_ext_m, &nic_mask);
    9674         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9675                 :            :                  ipv6_frag_ext_v->hdr.next_header &
    9676                 :            :                  ipv6_frag_ext_m->hdr.next_header);
    9677                 :            : }
    9678                 :            : 
    9679                 :            : /**
    9680                 :            :  * Add TCP item to the value.
    9681                 :            :  *
    9682                 :            :  * @param[in, out] key
    9683                 :            :  *   Flow matcher value.
    9684                 :            :  * @param[in] item
    9685                 :            :  *   Flow pattern to translate.
    9686                 :            :  * @param[in] inner
    9687                 :            :  *   Item is inner pattern.
    9688                 :            :  * @param[in] key_type
    9689                 :            :  *   Set flow matcher mask or value.
    9690                 :            :  */
    9691                 :            : static void
    9692                 :          0 : flow_dv_translate_item_tcp(void *key, const struct rte_flow_item *item,
    9693                 :            :                            int inner, uint32_t key_type)
    9694                 :            : {
    9695                 :            :         const struct rte_flow_item_tcp *tcp_m;
    9696                 :            :         const struct rte_flow_item_tcp *tcp_v;
    9697                 :            :         void *headers_v;
    9698                 :            : 
    9699         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9700                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9701         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9702         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9703                 :            :                          ip_protocol, 0xff);
    9704                 :            :         else
    9705         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9706                 :            :                          ip_protocol, IPPROTO_TCP);
    9707   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9708                 :            :                 return;
    9709   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, tcp_v, tcp_m,
             #  #  #  # ]
    9710                 :            :                          &rte_flow_item_tcp_mask);
    9711   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,
    9712                 :            :                  rte_be_to_cpu_16(tcp_v->hdr.src_port & tcp_m->hdr.src_port));
    9713   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,
    9714                 :            :                  rte_be_to_cpu_16(tcp_v->hdr.dst_port & tcp_m->hdr.dst_port));
    9715         [ #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
    9716                 :            :                  tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags);
    9717                 :            : }
    9718                 :            : 
    9719                 :            : /**
    9720                 :            :  * Add ESP item to the value.
    9721                 :            :  *
    9722                 :            :  * @param[in, out] key
    9723                 :            :  *   Flow matcher value.
    9724                 :            :  * @param[in] item
    9725                 :            :  *   Flow pattern to translate.
    9726                 :            :  * @param[in] inner
    9727                 :            :  *   Item is inner pattern.
    9728                 :            :  * @param[in] key_type
    9729                 :            :  *   Set flow matcher mask or value.
    9730                 :            :  */
    9731                 :            : static void
    9732                 :          0 : flow_dv_translate_item_esp(void *key, const struct rte_flow_item *item,
    9733                 :            :                            int inner, uint32_t key_type, uint64_t item_flags)
    9734                 :            : {
    9735                 :            :         const struct rte_flow_item_esp *esp_m;
    9736                 :            :         const struct rte_flow_item_esp *esp_v;
    9737                 :            :         void *headers_v;
    9738                 :            :         char *spi_v;
    9739         [ #  # ]:          0 :         bool over_udp = item_flags & (inner ? MLX5_FLOW_LAYER_INNER_L4_UDP :
    9740                 :            :                                               MLX5_FLOW_LAYER_OUTER_L4_UDP);
    9741                 :            : 
    9742         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9743                 :            :                             MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9744         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
    9745         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xff);
    9746   [ #  #  #  #  :          0 :                 if (over_udp && !MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport))
                   #  # ]
    9747         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, 0xFFFF);
    9748                 :            :         } else {
    9749         [ #  # ]:          0 :                 if (!over_udp)
    9750         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ESP);
    9751                 :            :                 else
    9752   [ #  #  #  # ]:          0 :                         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport))
    9753         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
    9754                 :            :                                          MLX5_UDP_PORT_ESP);
    9755                 :            :         }
    9756   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9757                 :            :                 return;
    9758   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, esp_v, esp_m, &rte_flow_item_esp_mask);
             #  #  #  # ]
    9759                 :            :         headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9760         [ #  # ]:          0 :         spi_v = inner ? MLX5_ADDR_OF(fte_match_set_misc, headers_v, inner_esp_spi) :
    9761                 :            :                         MLX5_ADDR_OF(fte_match_set_misc, headers_v, outer_esp_spi);
    9762                 :          0 :         *(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
    9763                 :            : }
    9764                 :            : 
    9765                 :            : /**
    9766                 :            :  * Add UDP item to the value.
    9767                 :            :  *
    9768                 :            :  * @param[in, out] key
    9769                 :            :  *   Flow matcher value.
    9770                 :            :  * @param[in] item
    9771                 :            :  *   Flow pattern to translate.
    9772                 :            :  * @param[in] inner
    9773                 :            :  *   Item is inner pattern.
    9774                 :            :  * @param[in] key_type
    9775                 :            :  *   Set flow matcher mask or value.
    9776                 :            :  */
    9777                 :            : static void
    9778                 :          0 : flow_dv_translate_item_udp(void *key, const struct rte_flow_item *item,
    9779                 :            :                            int inner, struct mlx5_dv_matcher_workspace *wks,
    9780                 :            :                            uint32_t key_type)
    9781                 :            : {
    9782                 :            :         const struct rte_flow_item_udp *udp_m;
    9783                 :            :         const struct rte_flow_item_udp *udp_v;
    9784                 :            :         void *headers_v;
    9785                 :            : 
    9786         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
    9787                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9788         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9789         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9790                 :            :                          ip_protocol, 0xff);
    9791                 :            :         else
    9792         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
    9793                 :            :                          ip_protocol, IPPROTO_UDP);
    9794   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9795                 :            :                 return;
    9796   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, udp_v, udp_m,
             #  #  #  # ]
    9797                 :            :                          &rte_flow_item_udp_mask);
    9798   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
    9799                 :            :                  rte_be_to_cpu_16(udp_v->hdr.src_port & udp_m->hdr.src_port));
    9800   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
    9801                 :            :                  rte_be_to_cpu_16(udp_v->hdr.dst_port & udp_m->hdr.dst_port));
    9802                 :            :         /* Force get UDP dport in case to be used in VXLAN translate. */
    9803         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW) {
    9804                 :          0 :                 udp_v = item->spec;
    9805         [ #  # ]:          0 :                 wks->udp_dport = rte_be_to_cpu_16(udp_v->hdr.dst_port &
    9806                 :            :                                                   udp_m->hdr.dst_port);
    9807                 :            :         }
    9808                 :            : }
    9809                 :            : 
    9810                 :            : /**
    9811                 :            :  * Add GRE optional Key item to the value.
    9812                 :            :  *
    9813                 :            :  * @param[in, out] key
    9814                 :            :  *   Flow matcher value.
    9815                 :            :  * @param[in] item
    9816                 :            :  *   Flow pattern to translate.
    9817                 :            :  * @param[in] inner
    9818                 :            :  *   Item is inner pattern.
    9819                 :            :  */
    9820                 :            : static void
    9821                 :          0 : flow_dv_translate_item_gre_key(void *key, const struct rte_flow_item *item,
    9822                 :            :                                uint32_t key_type)
    9823                 :            : {
    9824                 :            :         const rte_be32_t *key_m;
    9825                 :            :         const rte_be32_t *key_v;
    9826                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9827                 :          0 :         rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
    9828                 :            : 
    9829                 :            :         /* GRE K bit must be on and should already be validated */
    9830         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
    9831   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
    9832                 :          0 :                 return;
    9833   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, key_v, key_m,
             #  #  #  # ]
    9834                 :            :                          &gre_key_default_mask);
    9835   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_key_h,
    9836                 :            :                  rte_be_to_cpu_32((*key_v) & (*key_m)) >> 8);
    9837   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_key_l,
    9838                 :            :                  rte_be_to_cpu_32((*key_v) & (*key_m)) & 0xFF);
    9839                 :            : }
    9840                 :            : 
    9841                 :            : /**
    9842                 :            :  * Add GRE item to the value.
    9843                 :            :  *
    9844                 :            :  * @param[in, out] key
    9845                 :            :  *   Flow matcher value.
    9846                 :            :  * @param[in] item
    9847                 :            :  *   Flow pattern to translate.
    9848                 :            :  * @param[in] pattern_flags
    9849                 :            :  *   Accumulated pattern flags.
    9850                 :            :  * @param[in] key_type
    9851                 :            :  *   Set flow matcher mask or value.
    9852                 :            :  */
    9853                 :            : static void
    9854                 :          0 : flow_dv_translate_item_gre(void *key, const struct rte_flow_item *item,
    9855                 :            :                            uint64_t pattern_flags, uint32_t key_type)
    9856                 :            : {
    9857                 :            :         static const struct rte_flow_item_gre empty_gre = {0,};
    9858                 :          0 :         const struct rte_flow_item_gre *gre_m = item->mask;
    9859                 :          0 :         const struct rte_flow_item_gre *gre_v = item->spec;
    9860                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
    9861                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
    9862                 :            :         struct {
    9863                 :            :                 union {
    9864                 :            :                         __extension__
    9865                 :            :                         struct {
    9866                 :            :                                 uint16_t version:3;
    9867                 :            :                                 uint16_t rsvd0:9;
    9868                 :            :                                 uint16_t s_present:1;
    9869                 :            :                                 uint16_t k_present:1;
    9870                 :            :                                 uint16_t rsvd_bit1:1;
    9871                 :            :                                 uint16_t c_present:1;
    9872                 :            :                         };
    9873                 :            :                         uint16_t value;
    9874                 :            :                 };
    9875                 :            :         } gre_crks_rsvd0_ver_m, gre_crks_rsvd0_ver_v;
    9876                 :            :         uint16_t protocol_m, protocol_v;
    9877                 :            : 
    9878                 :            :         /* Common logic to SWS/HWS */
    9879         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
    9880         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xff);
    9881                 :            :         else
    9882         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
    9883                 :            :                         IPPROTO_GRE);
    9884                 :            :         /* HWS mask logic only */
    9885         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_HS_M) {
    9886         [ #  # ]:          0 :                 if (!gre_m)
    9887                 :            :                         gre_m = &empty_gre;
    9888                 :            :                 gre_v = gre_m;
    9889         [ #  # ]:          0 :         } else if (!gre_v) {
    9890                 :            :                 gre_v = &empty_gre;
    9891                 :            :                 gre_m = &empty_gre;
    9892         [ #  # ]:          0 :         } else if (!gre_m) {
    9893                 :            :                 gre_m = &rte_flow_item_gre_mask;
    9894                 :            :         }
    9895                 :            :         /* SWS logic only */
    9896         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW_M)
    9897                 :            :                 gre_v = gre_m;
    9898         [ #  # ]:          0 :         gre_crks_rsvd0_ver_m.value = rte_be_to_cpu_16(gre_m->c_rsvd0_ver);
    9899         [ #  # ]:          0 :         gre_crks_rsvd0_ver_v.value = rte_be_to_cpu_16(gre_v->c_rsvd0_ver);
    9900         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_c_present,
    9901                 :            :                  gre_crks_rsvd0_ver_v.c_present &
    9902                 :            :                  gre_crks_rsvd0_ver_m.c_present);
    9903         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_k_present,
    9904                 :            :                  gre_crks_rsvd0_ver_v.k_present &
    9905                 :            :                  gre_crks_rsvd0_ver_m.k_present);
    9906         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_s_present,
    9907                 :            :                  gre_crks_rsvd0_ver_v.s_present &
    9908                 :            :                  gre_crks_rsvd0_ver_m.s_present);
    9909         [ #  # ]:          0 :         protocol_m = rte_be_to_cpu_16(gre_m->protocol);
    9910         [ #  # ]:          0 :         protocol_v = rte_be_to_cpu_16(gre_v->protocol);
    9911         [ #  # ]:          0 :         if (!protocol_m) {
    9912                 :            :                 /* Force next protocol to prevent matchers duplication */
    9913                 :            :                 protocol_v = mlx5_translate_tunnel_etypes(pattern_flags);
    9914                 :            :                 if (protocol_v)
    9915                 :            :                         protocol_m = 0xFFFF;
    9916                 :            :                 /* Restore the value to mask in mask case. */
    9917         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
    9918                 :            :                         protocol_v = protocol_m;
    9919                 :            :         }
    9920         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, gre_protocol,
    9921                 :            :                  protocol_m & protocol_v);
    9922                 :          0 : }
    9923                 :            : 
    9924                 :            : /**
    9925                 :            :  * Add GRE optional items to the value.
    9926                 :            :  *
    9927                 :            :  * @param[in, out] key
    9928                 :            :  *   Flow matcher value.
    9929                 :            :  * @param[in] item
    9930                 :            :  *   Flow pattern to translate.
    9931                 :            :  * @param[in] gre_item
    9932                 :            :  *   Pointer to gre_item.
    9933                 :            :  * @param[in] pattern_flags
    9934                 :            :  *   Accumulated pattern flags.
    9935                 :            :  * @param[in] key_type
    9936                 :            :  *   Set flow matcher mask or value.
    9937                 :            :  */
    9938                 :            : static void
    9939                 :          0 : flow_dv_translate_item_gre_option(void *key,
    9940                 :            :                                   const struct rte_flow_item *item,
    9941                 :            :                                   const struct rte_flow_item *gre_item,
    9942                 :            :                                   uint64_t pattern_flags, uint32_t key_type)
    9943                 :            : {
    9944                 :            :         void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
    9945                 :          0 :         const struct rte_flow_item_gre_opt *option_m = item->mask;
    9946                 :          0 :         const struct rte_flow_item_gre_opt *option_v = item->spec;
    9947                 :          0 :         const struct rte_flow_item_gre *gre_m = gre_item->mask;
    9948                 :          0 :         const struct rte_flow_item_gre *gre_v = gre_item->spec;
    9949                 :            :         static const struct rte_flow_item_gre empty_gre = {0};
    9950                 :            :         struct rte_flow_item gre_key_item;
    9951                 :            :         uint16_t c_rsvd0_ver_m, c_rsvd0_ver_v;
    9952                 :            :         uint16_t protocol_m, protocol_v;
    9953                 :            : 
    9954                 :            :         /*
    9955                 :            :          * If only match key field, keep using misc for matching.
    9956                 :            :          * If need to match checksum or sequence, using misc5 and do
    9957                 :            :          * not need using misc.
    9958                 :            :          */
    9959         [ #  # ]:          0 :         if (!(option_m->sequence.sequence ||
    9960         [ #  # ]:          0 :               option_m->checksum_rsvd.checksum)) {
    9961                 :          0 :                 flow_dv_translate_item_gre(key, gre_item, pattern_flags, key_type);
    9962                 :          0 :                 gre_key_item.spec = &option_v->key.key;
    9963                 :          0 :                 gre_key_item.mask = &option_m->key.key;
    9964                 :          0 :                 flow_dv_translate_item_gre_key(key, &gre_key_item, key_type);
    9965                 :          0 :                 return;
    9966                 :            :         }
    9967         [ #  # ]:          0 :         if (!gre_v) {
    9968                 :            :                 gre_v = &empty_gre;
    9969                 :            :                 gre_m = &empty_gre;
    9970                 :            :         } else {
    9971         [ #  # ]:          0 :                 if (!gre_m)
    9972                 :            :                         gre_m = &rte_flow_item_gre_mask;
    9973                 :            :         }
    9974                 :          0 :         protocol_v = gre_v->protocol;
    9975                 :          0 :         protocol_m = gre_m->protocol;
    9976         [ #  # ]:          0 :         if (!protocol_m) {
    9977                 :            :                 /* Force next protocol to prevent matchers duplication */
    9978                 :            :                 uint16_t ether_type =
    9979                 :            :                         mlx5_translate_tunnel_etypes(pattern_flags);
    9980                 :            :                 if (ether_type) {
    9981         [ #  # ]:          0 :                         protocol_v = rte_be_to_cpu_16(ether_type);
    9982                 :            :                         protocol_m = UINT16_MAX;
    9983                 :            :                 }
    9984                 :            :         }
    9985                 :          0 :         c_rsvd0_ver_v = gre_v->c_rsvd0_ver;
    9986                 :          0 :         c_rsvd0_ver_m = gre_m->c_rsvd0_ver;
    9987         [ #  # ]:          0 :         if (option_m->sequence.sequence) {
    9988                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x1000);
    9989                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x1000);
    9990                 :            :         }
    9991         [ #  # ]:          0 :         if (option_m->key.key) {
    9992                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x2000);
    9993                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x2000);
    9994                 :            :         }
    9995         [ #  # ]:          0 :         if (option_m->checksum_rsvd.checksum) {
    9996                 :          0 :                 c_rsvd0_ver_v |= RTE_BE16(0x8000);
    9997                 :          0 :                 c_rsvd0_ver_m |= RTE_BE16(0x8000);
    9998                 :            :         }
    9999         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   10000                 :            :                 c_rsvd0_ver_v = c_rsvd0_ver_m;
   10001                 :            :                 protocol_v = protocol_m;
   10002                 :            :                 option_v = option_m;
   10003                 :            :         }
   10004                 :            :         /*
   10005                 :            :          * Hardware parses GRE optional field into the fixed location,
   10006                 :            :          * do not need to adjust the tunnel dword indices.
   10007                 :            :          */
   10008   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0,
   10009                 :            :                  rte_be_to_cpu_32((c_rsvd0_ver_v | protocol_v << 16) &
   10010                 :            :                                   (c_rsvd0_ver_m | protocol_m << 16)));
   10011   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1,
   10012                 :            :                  rte_be_to_cpu_32(option_v->checksum_rsvd.checksum &
   10013                 :            :                                   option_m->checksum_rsvd.checksum));
   10014   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_2,
   10015                 :            :                  rte_be_to_cpu_32(option_v->key.key & option_m->key.key));
   10016   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_3,
   10017                 :            :                  rte_be_to_cpu_32(option_v->sequence.sequence &
   10018                 :            :                                   option_m->sequence.sequence));
   10019                 :            : }
   10020                 :            : 
   10021                 :            : /**
   10022                 :            :  * Add NVGRE item to matcher and to the value.
   10023                 :            :  *
   10024                 :            :  * @param[in, out] key
   10025                 :            :  *   Flow matcher value.
   10026                 :            :  * @param[in] item
   10027                 :            :  *   Flow pattern to translate.
   10028                 :            :  * @param[in] pattern_flags
   10029                 :            :  *   Accumulated pattern flags.
   10030                 :            :  * @param[in] key_type
   10031                 :            :  *   Set flow matcher mask or value.
   10032                 :            :  */
   10033                 :            : static void
   10034                 :          0 : flow_dv_translate_item_nvgre(void *key, const struct rte_flow_item *item,
   10035                 :            :                              unsigned long pattern_flags, uint32_t key_type)
   10036                 :            : {
   10037                 :            :         const struct rte_flow_item_nvgre *nvgre_m;
   10038                 :            :         const struct rte_flow_item_nvgre *nvgre_v;
   10039                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10040                 :            :         const char *tni_flow_id_m;
   10041                 :            :         const char *tni_flow_id_v;
   10042                 :            :         char *gre_key_v;
   10043                 :            :         int size;
   10044                 :            :         int i;
   10045                 :            : 
   10046                 :            :         /* For NVGRE, GRE header fields must be set with defined values. */
   10047                 :          0 :         const struct rte_flow_item_gre gre_spec = {
   10048                 :            :                 .c_rsvd0_ver = RTE_BE16(0x2000),
   10049                 :            :                 .protocol = RTE_BE16(RTE_ETHER_TYPE_TEB)
   10050                 :            :         };
   10051                 :          0 :         const struct rte_flow_item_gre gre_mask = {
   10052                 :            :                 .c_rsvd0_ver = RTE_BE16(0xB000),
   10053                 :            :                 .protocol = RTE_BE16(UINT16_MAX),
   10054                 :            :         };
   10055                 :          0 :         const struct rte_flow_item gre_item = {
   10056                 :            :                 .spec = &gre_spec,
   10057                 :            :                 .mask = &gre_mask,
   10058                 :            :                 .last = NULL,
   10059                 :            :         };
   10060                 :          0 :         flow_dv_translate_item_gre(key, &gre_item, pattern_flags, key_type);
   10061   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10062                 :          0 :                 return;
   10063   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, nvgre_v, nvgre_m,
             #  #  #  # ]
   10064                 :            :                     &rte_flow_item_nvgre_mask);
   10065                 :          0 :         tni_flow_id_m = (const char *)nvgre_m->tni;
   10066                 :          0 :         tni_flow_id_v = (const char *)nvgre_v->tni;
   10067                 :            :         size = sizeof(nvgre_m->tni) + sizeof(nvgre_m->flow_id);
   10068                 :          0 :         gre_key_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, gre_key_h);
   10069         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   10070                 :          0 :                 gre_key_v[i] = tni_flow_id_m[i] & tni_flow_id_v[i];
   10071                 :            : }
   10072                 :            : 
   10073                 :            : /**
   10074                 :            :  * Add VXLAN item to the value.
   10075                 :            :  *
   10076                 :            :  * @param[in] dev
   10077                 :            :  *   Pointer to the Ethernet device structure.
   10078                 :            :  * @param[in] attr
   10079                 :            :  *   Flow rule attributes.
   10080                 :            :  * @param[in, out] key
   10081                 :            :  *   Flow matcher value.
   10082                 :            :  * @param[in] item
   10083                 :            :  *   Flow pattern to translate.
   10084                 :            :  * @param[in] inner
   10085                 :            :  *   Item is inner pattern.
   10086                 :            :  * @param[in] wks
   10087                 :            :  *   Matcher workspace.
   10088                 :            :  * @param[in] key_type
   10089                 :            :  *   Set flow matcher mask or value.
   10090                 :            :  */
   10091                 :            : static void
   10092                 :          0 : flow_dv_translate_item_vxlan(struct rte_eth_dev *dev,
   10093                 :            :                              const struct rte_flow_attr *attr,
   10094                 :            :                              void *key, const struct rte_flow_item *item,
   10095                 :            :                              int inner, struct mlx5_dv_matcher_workspace *wks,
   10096                 :            :                              uint32_t key_type)
   10097                 :            : {
   10098                 :            :         const struct rte_flow_item_vxlan *vxlan_m;
   10099                 :            :         const struct rte_flow_item_vxlan *vxlan_v;
   10100                 :            :         void *headers_v;
   10101                 :            :         void *misc_v;
   10102                 :            :         void *misc5_v;
   10103                 :            :         uint32_t tunnel_v;
   10104                 :            :         char *vni_v;
   10105                 :            :         uint16_t dport;
   10106                 :            :         int size;
   10107                 :            :         int i;
   10108                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10109                 :          0 :         const struct rte_flow_item_vxlan nic_mask = {
   10110                 :            :                 .hdr.vni =  { 0xff, 0xff, 0xff },
   10111                 :            :                 .hdr.rsvd1 = 0xff,
   10112                 :            :         };
   10113                 :            : 
   10114                 :            :         misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
   10115         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   10116                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10117         [ #  # ]:          0 :         dport = item->type == RTE_FLOW_ITEM_TYPE_VXLAN ?
   10118                 :            :                 MLX5_UDP_PORT_VXLAN : MLX5_UDP_PORT_VXLAN_GPE;
   10119   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10120         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10121         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10122                 :            :                                  udp_dport, 0xFFFF);
   10123                 :            :                 else
   10124         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10125                 :            :                                  udp_dport, dport);
   10126                 :            :         }
   10127                 :            :         /*
   10128                 :            :          * Read the UDP dport to check if the value satisfies the VXLAN
   10129                 :            :          * matching with MISC5 for CX5.
   10130                 :            :          */
   10131         [ #  # ]:          0 :         if (wks->udp_dport)
   10132                 :            :                 dport = wks->udp_dport;
   10133   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10134                 :          0 :                 return;
   10135   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, vxlan_v, vxlan_m, &nic_mask);
             #  #  #  # ]
   10136                 :            :         if ((item->mask == &nic_mask) &&
   10137                 :            :             ((!attr->group && !(attr->transfer && priv->fdb_def_rule) &&
   10138                 :            :             !priv->sh->tunnel_header_0_1) ||
   10139                 :            :             ((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
   10140                 :            :             !priv->sh->misc5_cap)))
   10141                 :            :                 vxlan_m = &rte_flow_item_vxlan_mask;
   10142         [ #  # ]:          0 :         if ((priv->sh->steering_format_version ==
   10143         [ #  # ]:          0 :              MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 &&
   10144                 :          0 :              dport != MLX5_UDP_PORT_VXLAN) ||
   10145   [ #  #  #  #  :          0 :             (!attr->group && !(attr->transfer && priv->fdb_def_rule)) ||
             #  #  #  # ]
   10146   [ #  #  #  # ]:          0 :             ((attr->group || (attr->transfer && priv->fdb_def_rule)) &&
   10147         [ #  # ]:          0 :             !priv->sh->misc5_cap)) {
   10148                 :            :                 misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10149                 :            :                 size = sizeof(vxlan_m->hdr.vni);
   10150                 :          0 :                 vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, vxlan_vni);
   10151         [ #  # ]:          0 :                 for (i = 0; i < size; ++i)
   10152                 :          0 :                         vni_v[i] = vxlan_m->hdr.vni[i] & vxlan_v->hdr.vni[i];
   10153                 :            :                 return;
   10154                 :            :         }
   10155                 :          0 :         tunnel_v = (vxlan_v->hdr.vni[0] & vxlan_m->hdr.vni[0]) |
   10156                 :          0 :                    (vxlan_v->hdr.vni[1] & vxlan_m->hdr.vni[1]) << 8 |
   10157                 :          0 :                    (vxlan_v->hdr.vni[2] & vxlan_m->hdr.vni[2]) << 16;
   10158                 :          0 :         tunnel_v |= (vxlan_v->hdr.rsvd1 & vxlan_m->hdr.rsvd1) << 24;
   10159         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1, RTE_BE32(tunnel_v));
   10160                 :            : }
   10161                 :            : 
   10162                 :            : /**
   10163                 :            :  * Add VXLAN-GPE item to the value.
   10164                 :            :  *
   10165                 :            :  * @param[in, out] key
   10166                 :            :  *   Flow matcher value.
   10167                 :            :  * @param[in] item
   10168                 :            :  *   Flow pattern to translate.
   10169                 :            :  * @param[in] pattern_flags
   10170                 :            :  *   Item pattern flags.
   10171                 :            :  * @param[in] key_type
   10172                 :            :  *   Set flow matcher mask or value.
   10173                 :            :  */
   10174                 :            : 
   10175                 :            : static void
   10176                 :          0 : flow_dv_translate_item_vxlan_gpe(void *key, const struct rte_flow_item *item,
   10177                 :            :                                  const uint64_t pattern_flags,
   10178                 :            :                                  uint32_t key_type)
   10179                 :            : {
   10180                 :            :         static const struct rte_flow_item_vxlan_gpe dummy_vxlan_gpe_hdr = {{{0}}};
   10181                 :          0 :         const struct rte_flow_item_vxlan_gpe *vxlan_m = item->mask;
   10182                 :          0 :         const struct rte_flow_item_vxlan_gpe *vxlan_v = item->spec;
   10183                 :            :         /* The item was validated to be on the outer side */
   10184                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10185                 :            :         void *misc_v =
   10186                 :            :                 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10187                 :          0 :         char *vni_v =
   10188                 :            :                 MLX5_ADDR_OF(fte_match_set_misc3, misc_v, outer_vxlan_gpe_vni);
   10189                 :            :         int i, size = sizeof(vxlan_m->hdr.vni);
   10190                 :            :         uint8_t flags_m = 0xff;
   10191                 :            :         uint8_t flags_v = 0xc;
   10192                 :            :         uint8_t m_protocol, v_protocol;
   10193                 :            : 
   10194   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10195         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10196         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10197                 :            :                                  0xFFFF);
   10198                 :            :                 else
   10199         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10200                 :            :                                  MLX5_UDP_PORT_VXLAN_GPE);
   10201                 :            :         }
   10202         [ #  # ]:          0 :         if (!vxlan_v) {
   10203                 :            :                 vxlan_v = &dummy_vxlan_gpe_hdr;
   10204                 :            :                 vxlan_m = &dummy_vxlan_gpe_hdr;
   10205                 :            :         } else {
   10206         [ #  # ]:          0 :                 if (!vxlan_m)
   10207                 :            :                         vxlan_m = &rte_flow_item_vxlan_gpe_mask;
   10208                 :            :         }
   10209         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10210                 :            :                 vxlan_v = vxlan_m;
   10211         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
   10212                 :            :                 vxlan_m = vxlan_v;
   10213         [ #  # ]:          0 :         if (vxlan_m->hdr.flags) {
   10214                 :            :                 flags_m = vxlan_m->hdr.flags;
   10215                 :          0 :                 flags_v = vxlan_v->hdr.flags;
   10216                 :            :         }
   10217                 :          0 :         m_protocol = vxlan_m->hdr.protocol;
   10218                 :          0 :         v_protocol = vxlan_v->hdr.protocol;
   10219         [ #  # ]:          0 :         if (!m_protocol) {
   10220                 :            :                 /* Force next protocol to ensure next headers parsing. */
   10221         [ #  # ]:          0 :                 if (pattern_flags & MLX5_FLOW_ITEM_NSH)
   10222                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_NSH;
   10223         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L2)
   10224                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_ETH;
   10225         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV4)
   10226                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_IPV4;
   10227         [ #  # ]:          0 :                 else if (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV6)
   10228                 :            :                         v_protocol = RTE_VXLAN_GPE_TYPE_IPV6;
   10229         [ #  # ]:          0 :                 if (v_protocol)
   10230                 :            :                         m_protocol = 0xFF;
   10231                 :            :                 /* Restore the value to mask in mask case. */
   10232         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10233                 :            :                         v_protocol = m_protocol;
   10234                 :            :         }
   10235                 :            :         /*
   10236                 :            :          * If only match flags/protocol/vni field, keep using misc3 for matching.
   10237                 :            :          * If need to match rsvd0 or rsvd1, using misc5 and do not need using misc3.
   10238                 :            :          */
   10239   [ #  #  #  #  :          0 :         if (!(vxlan_m->hdr.rsvd0[0] || vxlan_m->hdr.rsvd0[1] || vxlan_m->hdr.rsvd1)) {
                   #  # ]
   10240         [ #  # ]:          0 :                 for (i = 0; i < size; ++i)
   10241                 :          0 :                         vni_v[i] = vxlan_m->hdr.vni[i] & vxlan_v->hdr.vni[i];
   10242         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc_v, outer_vxlan_gpe_flags,
   10243                 :            :                          flags_m & flags_v);
   10244         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc_v,
   10245                 :            :                          outer_vxlan_gpe_next_protocol, m_protocol & v_protocol);
   10246                 :            :         } else {
   10247                 :            :                 uint32_t tunnel_v;
   10248                 :            :                 void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
   10249                 :            : 
   10250                 :          0 :                 tunnel_v = (flags_m & flags_v) << 24 |
   10251                 :          0 :                            (vxlan_v->hdr.rsvd0[0] & vxlan_m->hdr.rsvd0[0]) << 16 |
   10252                 :          0 :                            (vxlan_v->hdr.rsvd0[1] & vxlan_m->hdr.rsvd0[1]) << 8 |
   10253                 :          0 :                            (m_protocol & v_protocol);
   10254         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_0, tunnel_v);
   10255                 :          0 :                 tunnel_v = (vxlan_v->hdr.vni[0] & vxlan_m->hdr.vni[0]) << 24 |
   10256                 :          0 :                            (vxlan_v->hdr.vni[1] & vxlan_m->hdr.vni[1]) << 16 |
   10257                 :          0 :                            (vxlan_v->hdr.vni[2] & vxlan_m->hdr.vni[2]) << 8 |
   10258                 :          0 :                            (vxlan_v->hdr.rsvd1 & vxlan_m->hdr.rsvd1);
   10259         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, tunnel_header_1, tunnel_v);
   10260                 :            :         }
   10261                 :          0 : }
   10262                 :            : 
   10263                 :            : /**
   10264                 :            :  * Add Geneve item to the value.
   10265                 :            :  *
   10266                 :            :  * @param[in, out] key
   10267                 :            :  *   Flow matcher value.
   10268                 :            :  * @param[in] item
   10269                 :            :  *   Flow pattern to translate.
   10270                 :            :  * @param[in] pattern_flags
   10271                 :            :  *   Item pattern flags.
   10272                 :            :  * @param[in] key_type
   10273                 :            :  *   Set flow matcher mask or value.
   10274                 :            :  */
   10275                 :            : 
   10276                 :            : static void
   10277                 :          0 : flow_dv_translate_item_geneve(void *key, const struct rte_flow_item *item,
   10278                 :            :                               uint64_t pattern_flags, uint32_t key_type)
   10279                 :            : {
   10280                 :            :         static const struct rte_flow_item_geneve empty_geneve = {0,};
   10281                 :          0 :         const struct rte_flow_item_geneve *geneve_m = item->mask;
   10282                 :          0 :         const struct rte_flow_item_geneve *geneve_v = item->spec;
   10283                 :            :         /* GENEVE flow item validation allows single tunnel item */
   10284                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10285                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10286                 :            :         uint16_t gbhdr_m;
   10287                 :            :         uint16_t gbhdr_v;
   10288                 :          0 :         char *vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, geneve_vni);
   10289                 :            :         size_t size = sizeof(geneve_m->vni), i;
   10290                 :            :         uint16_t protocol_m, protocol_v;
   10291                 :            : 
   10292   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10293         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10294         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10295                 :            :                                  0xFFFF);
   10296                 :            :                 else
   10297         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
   10298                 :            :                                  MLX5_UDP_PORT_GENEVE);
   10299                 :            :         }
   10300         [ #  # ]:          0 :         if (!geneve_v) {
   10301                 :            :                 geneve_v = &empty_geneve;
   10302                 :            :                 geneve_m = &empty_geneve;
   10303                 :            :         } else {
   10304         [ #  # ]:          0 :                 if (!geneve_m)
   10305                 :            :                         geneve_m = &rte_flow_item_geneve_mask;
   10306                 :            :         }
   10307         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10308                 :            :                 geneve_v = geneve_m;
   10309         [ #  # ]:          0 :         else if (key_type == MLX5_SET_MATCHER_HS_V)
   10310                 :            :                 geneve_m = geneve_v;
   10311         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   10312                 :          0 :                 vni_v[i] = geneve_m->vni[i] & geneve_v->vni[i];
   10313         [ #  # ]:          0 :         gbhdr_m = rte_be_to_cpu_16(geneve_m->ver_opt_len_o_c_rsvd0);
   10314         [ #  # ]:          0 :         gbhdr_v = rte_be_to_cpu_16(geneve_v->ver_opt_len_o_c_rsvd0);
   10315         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_oam,
   10316                 :            :                  MLX5_GENEVE_OAMF_VAL(gbhdr_v) & MLX5_GENEVE_OAMF_VAL(gbhdr_m));
   10317         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len,
   10318                 :            :                  MLX5_GENEVE_OPTLEN_VAL(gbhdr_v) &
   10319                 :            :                  MLX5_GENEVE_OPTLEN_VAL(gbhdr_m));
   10320         [ #  # ]:          0 :         protocol_m = rte_be_to_cpu_16(geneve_m->protocol);
   10321         [ #  # ]:          0 :         protocol_v = rte_be_to_cpu_16(geneve_v->protocol);
   10322         [ #  # ]:          0 :         if (!protocol_m) {
   10323                 :            :                 /* Force next protocol to prevent matchers duplication */
   10324                 :            :                 protocol_v = mlx5_translate_tunnel_etypes(pattern_flags);
   10325                 :            :                 if (protocol_v)
   10326                 :            :                         protocol_m = 0xFFFF;
   10327                 :            :                 /* Restore the value to mask in mask case. */
   10328         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   10329                 :            :                         protocol_v = protocol_m;
   10330                 :            :         }
   10331         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, geneve_protocol_type,
   10332                 :            :                  protocol_m & protocol_v);
   10333                 :          0 : }
   10334                 :            : 
   10335                 :            : /**
   10336                 :            :  * Create Geneve TLV option resource.
   10337                 :            :  *
   10338                 :            :  * @param[in, out] dev
   10339                 :            :  *   Pointer to rte_eth_dev structure.
   10340                 :            :  * @param[in] item
   10341                 :            :  *   Flow pattern to translate.
   10342                 :            :  * @param[out] error
   10343                 :            :  *   pointer to error structure.
   10344                 :            :  *
   10345                 :            :  * @return
   10346                 :            :  *   0 on success otherwise -errno and errno is set.
   10347                 :            :  */
   10348                 :            : static int
   10349                 :          0 : flow_dev_geneve_tlv_option_resource_register(struct rte_eth_dev *dev,
   10350                 :            :                                              const struct rte_flow_item *item,
   10351                 :            :                                              struct rte_flow_error *error)
   10352                 :            : {
   10353                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10354                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   10355                 :          0 :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource =
   10356                 :            :                         sh->geneve_tlv_option_resource;
   10357                 :            :         struct mlx5_devx_obj *obj;
   10358                 :          0 :         const struct rte_flow_item_geneve_opt *geneve_opt_v = item->spec;
   10359                 :            :         int ret = 0;
   10360                 :            : 
   10361                 :            :         MLX5_ASSERT(sh->config.dv_flow_en == 1);
   10362         [ #  # ]:          0 :         if (!geneve_opt_v)
   10363                 :            :                 return -1;
   10364                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
   10365         [ #  # ]:          0 :         if (geneve_opt_resource != NULL) {
   10366                 :          0 :                 if (geneve_opt_resource->option_class ==
   10367                 :            :                         geneve_opt_v->option_class &&
   10368                 :            :                         geneve_opt_resource->option_type ==
   10369         [ #  # ]:          0 :                         geneve_opt_v->option_type &&
   10370                 :            :                         geneve_opt_resource->length ==
   10371                 :            :                         geneve_opt_v->option_len) {
   10372                 :          0 :                         rte_atomic_fetch_add_explicit(&geneve_opt_resource->refcnt, 1,
   10373                 :            :                                            rte_memory_order_relaxed);
   10374                 :            :                 } else {
   10375                 :          0 :                         ret = rte_flow_error_set(error, ENOMEM,
   10376                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10377                 :            :                                 "Only one GENEVE TLV option supported");
   10378                 :          0 :                         goto exit;
   10379                 :            :                 }
   10380                 :            :         } else {
   10381                 :          0 :                 struct mlx5_devx_geneve_tlv_option_attr attr = {
   10382                 :          0 :                         .option_class = geneve_opt_v->option_class,
   10383                 :          0 :                         .option_type = geneve_opt_v->option_type,
   10384                 :          0 :                         .option_data_len = geneve_opt_v->option_len,
   10385                 :            :                 };
   10386                 :            : 
   10387                 :            :                 /* Create a GENEVE TLV object and resource. */
   10388                 :          0 :                 obj = mlx5_devx_cmd_create_geneve_tlv_option(sh->cdev->ctx,
   10389                 :            :                                                              &attr);
   10390         [ #  # ]:          0 :                 if (!obj) {
   10391                 :          0 :                         ret = rte_flow_error_set(error, ENODATA,
   10392                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10393                 :            :                                 "Failed to create GENEVE TLV Devx object");
   10394                 :          0 :                         goto exit;
   10395                 :            :                 }
   10396                 :          0 :                 sh->geneve_tlv_option_resource =
   10397                 :          0 :                                 mlx5_malloc(MLX5_MEM_ZERO,
   10398                 :            :                                                 sizeof(*geneve_opt_resource),
   10399                 :            :                                                 0, SOCKET_ID_ANY);
   10400         [ #  # ]:          0 :                 if (!sh->geneve_tlv_option_resource) {
   10401                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy(obj));
   10402                 :          0 :                         ret = rte_flow_error_set(error, ENOMEM,
   10403                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   10404                 :            :                                 "GENEVE TLV object memory allocation failed");
   10405                 :          0 :                         goto exit;
   10406                 :            :                 }
   10407                 :            :                 geneve_opt_resource = sh->geneve_tlv_option_resource;
   10408                 :          0 :                 geneve_opt_resource->obj = obj;
   10409                 :          0 :                 geneve_opt_resource->option_class = geneve_opt_v->option_class;
   10410                 :          0 :                 geneve_opt_resource->option_type = geneve_opt_v->option_type;
   10411                 :          0 :                 geneve_opt_resource->length = geneve_opt_v->option_len;
   10412                 :          0 :                 rte_atomic_store_explicit(&geneve_opt_resource->refcnt, 1,
   10413                 :            :                                 rte_memory_order_relaxed);
   10414                 :            :         }
   10415                 :          0 : exit:
   10416                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
   10417                 :          0 :         return ret;
   10418                 :            : }
   10419                 :            : 
   10420                 :            : /**
   10421                 :            :  * Add Geneve TLV option item to value.
   10422                 :            :  *
   10423                 :            :  * @param[in, out] dev
   10424                 :            :  *   Pointer to rte_eth_dev structure.
   10425                 :            :  * @param[in, out] key
   10426                 :            :  *   Flow matcher value.
   10427                 :            :  * @param[in] item
   10428                 :            :  *   Flow pattern to translate.
   10429                 :            :  * @param[in] key_type
   10430                 :            :  *   Set flow matcher mask or value.
   10431                 :            :  * @param[out] error
   10432                 :            :  *   Pointer to error structure.
   10433                 :            :  */
   10434                 :            : static int
   10435                 :          0 : flow_dv_translate_item_geneve_opt(struct rte_eth_dev *dev, void *key,
   10436                 :            :                                   const struct rte_flow_item *item,
   10437                 :            :                                   uint32_t key_type,
   10438                 :            :                                   struct rte_flow_error *error)
   10439                 :            : {
   10440                 :            :         const struct rte_flow_item_geneve_opt *geneve_opt_m;
   10441                 :            :         const struct rte_flow_item_geneve_opt *geneve_opt_v;
   10442                 :          0 :         const struct rte_flow_item_geneve_opt *orig_spec = item->spec;
   10443                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   10444                 :          0 :         rte_be32_t opt_data_key = 0, opt_data_mask = 0;
   10445                 :            :         size_t option_byte_len;
   10446                 :            :         int ret = 0;
   10447                 :            : 
   10448   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type) || !orig_spec)
          #  #  #  #  #  
                #  #  # ]
   10449                 :            :                 return -1;
   10450   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, geneve_opt_v, geneve_opt_m,
             #  #  #  # ]
   10451                 :            :                          &rte_flow_item_geneve_opt_mask);
   10452                 :            :         /*
   10453                 :            :          * Register resource requires item spec for SW steering,
   10454                 :            :          * for HW steering resources is registered explicitly by user.
   10455                 :            :          */
   10456         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW_V) {
   10457                 :          0 :                 ret = flow_dev_geneve_tlv_option_resource_register(dev, item,
   10458                 :            :                                                                    error);
   10459         [ #  # ]:          0 :                 if (ret) {
   10460                 :          0 :                         DRV_LOG(ERR, "Failed to create geneve_tlv_obj");
   10461                 :          0 :                         return ret;
   10462                 :            :                 }
   10463                 :            :         }
   10464                 :            :         /* Convert the option length from DW to bytes for using memcpy. */
   10465                 :          0 :         option_byte_len = RTE_MIN((size_t)(orig_spec->option_len * 4),
   10466                 :            :                                   sizeof(rte_be32_t));
   10467         [ #  # ]:          0 :         if (geneve_opt_v->data) {
   10468                 :            :                 memcpy(&opt_data_key, geneve_opt_v->data, option_byte_len);
   10469                 :          0 :                 memcpy(&opt_data_mask, geneve_opt_m->data, option_byte_len);
   10470   [ #  #  #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v,
   10471                 :            :                          geneve_tlv_option_0_data,
   10472                 :            :                          rte_be_to_cpu_32(opt_data_key & opt_data_mask));
   10473                 :            :         }
   10474                 :            :         return ret;
   10475                 :            : }
   10476                 :            : 
   10477                 :            : /**
   10478                 :            :  * Add MPLS item to the value.
   10479                 :            :  *
   10480                 :            :  * @param[in, out] key
   10481                 :            :  *   Flow matcher value.
   10482                 :            :  * @param[in] item
   10483                 :            :  *   Flow pattern to translate.
   10484                 :            :  * @param[in] prev_layer
   10485                 :            :  *   The protocol layer indicated in previous item.
   10486                 :            :  * @param[in] inner
   10487                 :            :  *   Item is inner pattern.
   10488                 :            :  * @param[in] key_type
   10489                 :            :  *   Set flow matcher mask or value.
   10490                 :            :  */
   10491                 :            : static void
   10492                 :          0 : flow_dv_translate_item_mpls(void *key, const struct rte_flow_item *item,
   10493                 :            :                             uint64_t prev_layer, int inner,
   10494                 :            :                             uint32_t key_type)
   10495                 :            : {
   10496                 :            :         const uint32_t *in_mpls_m;
   10497                 :            :         const uint32_t *in_mpls_v;
   10498                 :            :         uint32_t *out_mpls_v = 0;
   10499                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10500                 :          0 :         void *misc2_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
   10501                 :            :         void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   10502                 :            : 
   10503      [ #  #  # ]:          0 :         switch (prev_layer) {
   10504                 :          0 :         case MLX5_FLOW_LAYER_OUTER_L4_UDP:
   10505   [ #  #  #  # ]:          0 :                 if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   10506         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10507         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10508                 :            :                                          udp_dport, 0xffff);
   10509                 :            :                         else
   10510         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   10511                 :            :                                          udp_dport, MLX5_UDP_PORT_MPLS);
   10512                 :            :                 }
   10513                 :            :                 break;
   10514                 :          0 :         case MLX5_FLOW_LAYER_GRE:
   10515                 :            :                 /* Fall-through. */
   10516                 :            :         case MLX5_FLOW_LAYER_GRE_KEY:
   10517   [ #  #  #  # ]:          0 :                 if (!MLX5_GET16(fte_match_set_misc, misc_v, gre_protocol)) {
   10518         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   10519         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_misc, misc_v,
   10520                 :            :                                          gre_protocol, 0xffff);
   10521                 :            :                         else
   10522         [ #  # ]:          0 :                                 MLX5_SET(fte_match_set_misc, misc_v,
   10523                 :            :                                          gre_protocol, RTE_ETHER_TYPE_MPLS);
   10524                 :            :                 }
   10525                 :            :                 break;
   10526                 :            :         default:
   10527                 :            :                 break;
   10528                 :            :         }
   10529   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10530                 :            :                 return;
   10531   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, in_mpls_v, in_mpls_m,
             #  #  #  # ]
   10532                 :            :                          &rte_flow_item_mpls_mask);
   10533      [ #  #  # ]:          0 :         switch (prev_layer) {
   10534                 :          0 :         case MLX5_FLOW_LAYER_OUTER_L4_UDP:
   10535                 :          0 :                 out_mpls_v =
   10536                 :            :                         (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
   10537                 :            :                                                  outer_first_mpls_over_udp);
   10538                 :          0 :                 break;
   10539                 :          0 :         case MLX5_FLOW_LAYER_GRE:
   10540                 :          0 :                 out_mpls_v =
   10541                 :            :                         (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
   10542                 :            :                                                  outer_first_mpls_over_gre);
   10543                 :          0 :                 break;
   10544                 :          0 :         default:
   10545                 :            :                 /* Inner MPLS not over GRE is not supported. */
   10546         [ #  # ]:          0 :                 if (!inner)
   10547                 :            :                         out_mpls_v =
   10548                 :            :                                 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2,
   10549                 :            :                                                          misc2_v,
   10550                 :            :                                                          outer_first_mpls);
   10551                 :            :                 break;
   10552                 :            :         }
   10553                 :            :         if (out_mpls_v)
   10554                 :          0 :                 *out_mpls_v = *in_mpls_v & *in_mpls_m;
   10555                 :            : }
   10556                 :            : 
   10557                 :            : /**
   10558                 :            :  * Add metadata register item to matcher
   10559                 :            :  *
   10560                 :            :  * @param[in, out] key
   10561                 :            :  *   Flow matcher value.
   10562                 :            :  * @param[in] reg_type
   10563                 :            :  *   Type of device metadata register
   10564                 :            :  * @param[in] data
   10565                 :            :  *   Register data
   10566                 :            :  * @param[in] mask
   10567                 :            :  *   Register mask
   10568                 :            :  */
   10569                 :            : static void
   10570                 :          0 : flow_dv_match_meta_reg(void *key, enum modify_reg reg_type,
   10571                 :            :                        uint32_t data, uint32_t mask)
   10572                 :            : {
   10573                 :            :         void *misc2_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
   10574                 :            :         void *misc5_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_5);
   10575                 :            :         uint32_t temp;
   10576                 :            : 
   10577         [ #  # ]:          0 :         if (!key)
   10578                 :            :                 return;
   10579                 :          0 :         data &= mask;
   10580   [ #  #  #  #  :          0 :         switch (reg_type) {
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
   10581                 :          0 :         case REG_A:
   10582         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_a, data);
   10583                 :          0 :                 break;
   10584                 :          0 :         case REG_B:
   10585         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_b, data);
   10586                 :          0 :                 break;
   10587                 :          0 :         case REG_C_0:
   10588                 :            :                 /*
   10589                 :            :                  * The metadata register C0 field might be divided into
   10590                 :            :                  * source vport index and META item value, we should set
   10591                 :            :                  * this field according to specified mask, not as whole one.
   10592                 :            :                  */
   10593         [ #  # ]:          0 :                 temp = MLX5_GET(fte_match_set_misc2, misc2_v, metadata_reg_c_0);
   10594         [ #  # ]:          0 :                 if (mask)
   10595                 :          0 :                         temp &= ~mask;
   10596                 :          0 :                 temp |= data;
   10597         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, temp);
   10598                 :          0 :                 break;
   10599                 :          0 :         case REG_C_1:
   10600         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_1, data);
   10601                 :          0 :                 break;
   10602                 :          0 :         case REG_C_2:
   10603         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_2, data);
   10604                 :          0 :                 break;
   10605                 :          0 :         case REG_C_3:
   10606         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_3, data);
   10607                 :          0 :                 break;
   10608                 :          0 :         case REG_C_4:
   10609         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_4, data);
   10610                 :          0 :                 break;
   10611                 :          0 :         case REG_C_5:
   10612         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_5, data);
   10613                 :          0 :                 break;
   10614                 :          0 :         case REG_C_6:
   10615         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_6, data);
   10616                 :          0 :                 break;
   10617                 :          0 :         case REG_C_7:
   10618         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_7, data);
   10619                 :          0 :                 break;
   10620                 :          0 :         case REG_C_8:
   10621         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, metadata_reg_c_8, data);
   10622                 :          0 :                 break;
   10623                 :          0 :         case REG_C_9:
   10624         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, metadata_reg_c_9, data);
   10625                 :          0 :                 break;
   10626                 :          0 :         case REG_C_10:
   10627         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, metadata_reg_c_10, data);
   10628                 :          0 :                 break;
   10629                 :          0 :         case REG_C_11:
   10630         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc5, misc5_v, metadata_reg_c_11, data);
   10631                 :          0 :                 break;
   10632                 :            :         default:
   10633                 :            :                 MLX5_ASSERT(false);
   10634                 :            :                 break;
   10635                 :            :         }
   10636                 :            : }
   10637                 :            : 
   10638                 :            : /**
   10639                 :            :  * Add metadata register item to matcher
   10640                 :            :  *
   10641                 :            :  * @param[in, out] matcher
   10642                 :            :  *   Flow matcher.
   10643                 :            :  * @param[in, out] key
   10644                 :            :  *   Flow matcher value.
   10645                 :            :  * @param[in] reg_type
   10646                 :            :  *   Type of device metadata register
   10647                 :            :  * @param[in] value
   10648                 :            :  *   Register value
   10649                 :            :  * @param[in] mask
   10650                 :            :  *   Register mask
   10651                 :            :  */
   10652                 :            : static void
   10653                 :            : flow_dv_match_meta_reg_all(void *matcher, void *key, enum modify_reg reg_type,
   10654                 :            :                            uint32_t data, uint32_t mask)
   10655                 :            : {
   10656                 :          0 :         flow_dv_match_meta_reg(key, reg_type, data, mask);
   10657                 :          0 :         flow_dv_match_meta_reg(matcher, reg_type, mask, mask);
   10658                 :            : }
   10659                 :            : 
   10660                 :            : /**
   10661                 :            :  * Add MARK item to matcher
   10662                 :            :  *
   10663                 :            :  * @param[in] dev
   10664                 :            :  *   The device to configure through.
   10665                 :            :  * @param[in, out] key
   10666                 :            :  *   Flow matcher value.
   10667                 :            :  * @param[in] item
   10668                 :            :  *   Flow pattern to translate.
   10669                 :            :  * @param[in] key_type
   10670                 :            :  *   Set flow matcher mask or value.
   10671                 :            :  */
   10672                 :            : static void
   10673                 :          0 : flow_dv_translate_item_mark(struct rte_eth_dev *dev, void *key,
   10674                 :            :                             const struct rte_flow_item *item,
   10675                 :            :                             uint32_t key_type)
   10676                 :            : {
   10677                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   10678                 :            :         const struct rte_flow_item_mark *mark;
   10679                 :            :         uint32_t value;
   10680                 :            :         uint32_t mask = 0;
   10681                 :            : 
   10682         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_SW) {
   10683         [ #  # ]:          0 :                 mark = item->mask ? (const void *)item->mask :
   10684                 :            :                                     &rte_flow_item_mark_mask;
   10685                 :          0 :                 mask = mark->id;
   10686         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M) {
   10687                 :            :                         value = mask;
   10688                 :            :                 } else {
   10689                 :          0 :                         mark = (const void *)item->spec;
   10690                 :            :                         MLX5_ASSERT(mark);
   10691                 :          0 :                         value = mark->id;
   10692                 :            :                 }
   10693                 :            :         } else {
   10694         [ #  # ]:          0 :                 mark = (key_type == MLX5_SET_MATCHER_HS_V) ?
   10695                 :            :                         (const void *)item->spec : (const void *)item->mask;
   10696                 :            :                 MLX5_ASSERT(mark);
   10697                 :          0 :                 value = mark->id;
   10698         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_HS_M)
   10699                 :            :                         mask = value;
   10700                 :            :         }
   10701                 :          0 :         mask &= priv->sh->dv_mark_mask;
   10702                 :          0 :         value &= mask;
   10703         [ #  # ]:          0 :         if (mask) {
   10704                 :            :                 enum modify_reg reg;
   10705                 :            : 
   10706                 :            :                 /* Get the metadata register index for the mark. */
   10707                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, NULL);
   10708                 :            :                 MLX5_ASSERT(reg > 0);
   10709         [ #  # ]:          0 :                 if (reg == REG_C_0) {
   10710                 :          0 :                         struct mlx5_priv *priv = dev->data->dev_private;
   10711                 :          0 :                         uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10712                 :            :                         uint32_t shl_c0 = rte_bsf32(msk_c0);
   10713                 :            : 
   10714                 :          0 :                         mask &= msk_c0;
   10715                 :          0 :                         mask <<= shl_c0;
   10716                 :          0 :                         value <<= shl_c0;
   10717                 :            :                 }
   10718                 :          0 :                 flow_dv_match_meta_reg(key, reg, value, mask);
   10719                 :            :         }
   10720                 :          0 : }
   10721                 :            : 
   10722                 :            : /**
   10723                 :            :  * Add META item to matcher
   10724                 :            :  *
   10725                 :            :  * @param[in] dev
   10726                 :            :  *   The devich to configure through.
   10727                 :            :  * @param[in, out] key
   10728                 :            :  *   Flow matcher value.
   10729                 :            :  * @param[in] attr
   10730                 :            :  *   Attributes of flow that includes this item.
   10731                 :            :  * @param[in] item
   10732                 :            :  *   Flow pattern to translate.
   10733                 :            :  * @param[in] key_type
   10734                 :            :  *   Set flow matcher mask or value.
   10735                 :            :  */
   10736                 :            : static void
   10737                 :          0 : flow_dv_translate_item_meta(struct rte_eth_dev *dev,
   10738                 :            :                             void *key,
   10739                 :            :                             const struct rte_flow_attr *attr,
   10740                 :            :                             const struct rte_flow_item *item,
   10741                 :            :                             uint32_t key_type)
   10742                 :            : {
   10743                 :            :         const struct rte_flow_item_meta *meta_m;
   10744                 :            :         const struct rte_flow_item_meta *meta_v;
   10745                 :            :         uint32_t value;
   10746                 :            :         uint32_t mask = 0;
   10747                 :            :         int reg;
   10748                 :            : 
   10749   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10750                 :            :                 return;
   10751   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, meta_v, meta_m,
             #  #  #  # ]
   10752                 :            :                          &rte_flow_item_meta_mask);
   10753                 :          0 :         value = meta_v->data;
   10754                 :          0 :         mask = meta_m->data;
   10755         [ #  # ]:          0 :         if (key_type == MLX5_SET_MATCHER_HS_M)
   10756                 :            :                 mask = value;
   10757                 :            :         /*
   10758                 :            :          * In the current implementation, REG_B cannot be used to match.
   10759                 :            :          * Force to use REG_C_1 in HWS root table as other tables.
   10760                 :            :          * This map may change.
   10761                 :            :          * NIC: modify - REG_B to be present in SW
   10762                 :            :          *      match - REG_C_1 when copied from FDB, different from SWS
   10763                 :            :          * FDB: modify - REG_C_1 in Xmeta mode, REG_NON in legacy mode
   10764                 :            :          *      match - REG_C_1 in FDB
   10765                 :            :          */
   10766         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   10767                 :          0 :                 reg = flow_dv_get_metadata_reg(dev, attr, NULL);
   10768                 :            :         else
   10769                 :            :                 reg = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_META, 0);
   10770         [ #  # ]:          0 :         if (reg < 0)
   10771                 :            :                 return;
   10772                 :            :         MLX5_ASSERT(reg != REG_NON);
   10773         [ #  # ]:          0 :         if (reg == REG_C_0) {
   10774                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
   10775                 :          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10776                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
   10777                 :            : 
   10778                 :          0 :                 mask &= msk_c0;
   10779                 :          0 :                 mask <<= shl_c0;
   10780                 :          0 :                 value <<= shl_c0;
   10781                 :            :         }
   10782                 :          0 :         flow_dv_match_meta_reg(key, reg, value, mask);
   10783                 :            : }
   10784                 :            : 
   10785                 :            : /**
   10786                 :            :  * Add vport metadata Reg C0 item to matcher
   10787                 :            :  *
   10788                 :            :  * @param[in, out] key
   10789                 :            :  *   Flow matcher value.
   10790                 :            :  * @param[in] value
   10791                 :            :  *   Register value
   10792                 :            :  * @param[in] mask
   10793                 :            :  *   Register mask
   10794                 :            :  */
   10795                 :            : static void
   10796                 :            : flow_dv_translate_item_meta_vport(void *key, uint32_t value, uint32_t mask)
   10797                 :            : {
   10798                 :          0 :         flow_dv_match_meta_reg(key, REG_C_0, value, mask);
   10799                 :          0 : }
   10800                 :            : 
   10801                 :            : /**
   10802                 :            :  * Add tag item to matcher
   10803                 :            :  *
   10804                 :            :  * @param[in] dev
   10805                 :            :  *   The devich to configure through.
   10806                 :            :  * @param[in, out] key
   10807                 :            :  *   Flow matcher value.
   10808                 :            :  * @param[in] item
   10809                 :            :  *   Flow pattern to translate.
   10810                 :            :  * @param[in] key_type
   10811                 :            :  *   Set flow matcher mask or value.
   10812                 :            :  */
   10813                 :            : static void
   10814                 :          0 : flow_dv_translate_mlx5_item_tag(struct rte_eth_dev *dev, void *key,
   10815                 :            :                                 const struct rte_flow_item *item,
   10816                 :            :                                 uint32_t key_type)
   10817                 :            : {
   10818                 :          0 :         const struct mlx5_rte_flow_item_tag *tag_v = item->spec;
   10819                 :          0 :         const struct mlx5_rte_flow_item_tag *tag_m = item->mask;
   10820                 :            :         uint32_t mask, value;
   10821                 :            : 
   10822                 :            :         MLX5_ASSERT(tag_v);
   10823                 :          0 :         value = tag_v->data;
   10824         [ #  # ]:          0 :         mask = tag_m ? tag_m->data : UINT32_MAX;
   10825         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   10826                 :            :                 value = mask;
   10827         [ #  # ]:          0 :         if (tag_v->id == REG_C_0) {
   10828                 :          0 :                 struct mlx5_priv *priv = dev->data->dev_private;
   10829                 :          0 :                 uint32_t msk_c0 = priv->sh->dv_regc0_mask;
   10830                 :            :                 uint32_t shl_c0 = rte_bsf32(msk_c0);
   10831                 :            : 
   10832                 :          0 :                 mask &= msk_c0;
   10833                 :          0 :                 mask <<= shl_c0;
   10834                 :          0 :                 value <<= shl_c0;
   10835                 :            :         }
   10836                 :          0 :         flow_dv_match_meta_reg(key, tag_v->id, value, mask);
   10837                 :          0 : }
   10838                 :            : 
   10839                 :            : /**
   10840                 :            :  * Add TAG item to matcher
   10841                 :            :  *
   10842                 :            :  * @param[in] dev
   10843                 :            :  *   The devich to configure through.
   10844                 :            :  * @param[in, out] key
   10845                 :            :  *   Flow matcher value.
   10846                 :            :  * @param[in] item
   10847                 :            :  *   Flow pattern to translate.
   10848                 :            :  * @param[in] key_type
   10849                 :            :  *   Set flow matcher mask or value.
   10850                 :            :  *
   10851                 :            :  * @return
   10852                 :            :  *   0 on success. Negative errno value otherwise.
   10853                 :            :  */
   10854                 :            : static int
   10855                 :          0 : flow_dv_translate_item_tag(struct rte_eth_dev *dev, void *key,
   10856                 :            :                            const struct rte_flow_item *item,
   10857                 :            :                            uint32_t key_type)
   10858                 :            : {
   10859                 :          0 :         const struct rte_flow_item_tag *tag_vv = item->spec;
   10860                 :            :         const struct rte_flow_item_tag *tag_v;
   10861                 :            :         const struct rte_flow_item_tag *tag_m;
   10862                 :            :         int reg;
   10863                 :            :         uint32_t index;
   10864                 :            : 
   10865   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   10866                 :            :                 return 0;
   10867   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, tag_v, tag_m,
             #  #  #  # ]
   10868                 :            :                 &rte_flow_item_tag_mask);
   10869                 :            :         /* When set mask, the index should be from spec. */
   10870         [ #  # ]:          0 :         index = tag_vv ? tag_vv->index : tag_v->index;
   10871                 :            :         /* Get the metadata register index for the tag. */
   10872         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   10873                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, index, NULL);
   10874                 :            :         else
   10875                 :            :                 reg = flow_hw_get_reg_id(dev, RTE_FLOW_ITEM_TYPE_TAG, index);
   10876         [ #  # ]:          0 :         if (reg < 0) {
   10877                 :          0 :                 DRV_LOG(ERR, "port %u tag index %u does not map to correct register",
   10878                 :            :                         dev->data->port_id, index);
   10879                 :          0 :                 return -EINVAL;
   10880                 :            :         }
   10881         [ #  # ]:          0 :         if (reg == REG_NON) {
   10882                 :          0 :                 DRV_LOG(ERR, "port %u tag index %u maps to unsupported register",
   10883                 :            :                         dev->data->port_id, index);
   10884                 :          0 :                 return -ENOTSUP;
   10885                 :            :         }
   10886                 :          0 :         flow_dv_match_meta_reg(key, (enum modify_reg)reg, tag_v->data, tag_m->data);
   10887                 :          0 :         return 0;
   10888                 :            : }
   10889                 :            : 
   10890                 :            : /**
   10891                 :            :  * Add source vport match to the specified matcher.
   10892                 :            :  *
   10893                 :            :  * @param[in, out] key
   10894                 :            :  *   Flow matcher value.
   10895                 :            :  * @param[in] port
   10896                 :            :  *   Source vport value to match
   10897                 :            :  */
   10898                 :            : static void
   10899                 :            : flow_dv_translate_item_source_vport(void *key,
   10900                 :            :                                     int16_t port)
   10901                 :            : {
   10902                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   10903                 :            : 
   10904   [ #  #  #  #  :          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_port, port);
                   #  # ]
   10905                 :          0 : }
   10906                 :            : 
   10907                 :            : /**
   10908                 :            :  * Translate port-id item to eswitch match on  port-id.
   10909                 :            :  *
   10910                 :            :  * @param[in] dev
   10911                 :            :  *   The devich to configure through.
   10912                 :            :  * @param[in, out] key
   10913                 :            :  *   Flow matcher value.
   10914                 :            :  * @param[in] item
   10915                 :            :  *   Flow pattern to translate.
   10916                 :            :  * @param[in] attr
   10917                 :            :  *   Flow attributes.
   10918                 :            :  * @param[in] key_type
   10919                 :            :  *   Set flow matcher mask or value.
   10920                 :            :  *
   10921                 :            :  * @return
   10922                 :            :  *   0 on success, a negative errno value otherwise.
   10923                 :            :  */
   10924                 :            : static int
   10925                 :          0 : flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *key,
   10926                 :            :                                const struct rte_flow_item *item,
   10927                 :            :                                const struct rte_flow_attr *attr,
   10928                 :            :                                uint32_t key_type)
   10929                 :            : {
   10930         [ #  # ]:          0 :         const struct rte_flow_item_port_id *pid_m = item ? item->mask : NULL;
   10931         [ #  # ]:          0 :         const struct rte_flow_item_port_id *pid_v = item ? item->spec : NULL;
   10932                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   10933                 :            :         struct mlx5_priv *priv;
   10934                 :            :         uint16_t mask, id;
   10935                 :            :         uint32_t vport_meta;
   10936                 :            : 
   10937                 :            :         MLX5_ASSERT(wks);
   10938   [ #  #  #  # ]:          0 :         if (pid_v && pid_v->id == MLX5_PORT_ESW_MGR) {
   10939                 :          0 :                 priv = dev->data->dev_private;
   10940         [ #  # ]:          0 :                 if (priv->sh->dev_cap.esw_info.regc_mask) {
   10941         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M) {
   10942                 :            :                                 vport_meta = priv->sh->dev_cap.esw_info.regc_mask;
   10943                 :            :                         } else {
   10944                 :          0 :                                 vport_meta = priv->sh->dev_cap.esw_info.regc_value;
   10945                 :          0 :                                 wks->vport_meta_tag = vport_meta;
   10946                 :            :                         }
   10947                 :            :                         flow_dv_translate_item_meta_vport(key, vport_meta,
   10948                 :            :                                                           priv->sh->dev_cap.esw_info.regc_mask);
   10949                 :            :                 } else {
   10950                 :          0 :                         flow_dv_translate_item_source_vport(key,
   10951         [ #  # ]:          0 :                                         key_type & MLX5_SET_MATCHER_V ?
   10952                 :          0 :                                         mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   10953                 :            :                 }
   10954                 :          0 :                 return 0;
   10955                 :            :         }
   10956         [ #  # ]:          0 :         mask = pid_m ? pid_m->id : 0xffff;
   10957         [ #  # ]:          0 :         id = pid_v ? pid_v->id : dev->data->port_id;
   10958                 :          0 :         priv = mlx5_port_to_eswitch_info(id, item == NULL);
   10959         [ #  # ]:          0 :         if (!priv)
   10960                 :          0 :                 return -rte_errno;
   10961         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   10962                 :            :                 id = mask;
   10963                 :          0 :                 vport_meta = priv->vport_meta_mask;
   10964                 :            :         } else {
   10965                 :          0 :                 id = priv->vport_id;
   10966                 :          0 :                 vport_meta = priv->vport_meta_tag;
   10967                 :          0 :                 wks->vport_meta_tag = vport_meta;
   10968                 :            :         }
   10969                 :            :         /*
   10970                 :            :          * Translate to vport field or to metadata, depending on mode.
   10971                 :            :          * Kernel can use either misc.source_port or half of C0 metadata
   10972                 :            :          * register.
   10973                 :            :          */
   10974         [ #  # ]:          0 :         if (priv->vport_meta_mask) {
   10975                 :            :                 /*
   10976                 :            :                  * Provide the hint for SW steering library
   10977                 :            :                  * to insert the flow into ingress domain and
   10978                 :            :                  * save the extra vport match.
   10979                 :            :                  */
   10980   [ #  #  #  # ]:          0 :                 if (mask == 0xffff && priv->vport_id == 0xffff &&
   10981   [ #  #  #  # ]:          0 :                     priv->pf_bond < 0 && attr->transfer)
   10982         [ #  # ]:          0 :                         flow_dv_translate_item_source_vport(key, id);
   10983                 :            :                 /*
   10984                 :            :                  * We should always set the vport metadata register,
   10985                 :            :                  * otherwise the SW steering library can drop
   10986                 :            :                  * the rule if wire vport metadata value is not zero,
   10987                 :            :                  * it depends on kernel configuration.
   10988                 :            :                  */
   10989                 :          0 :                 flow_dv_translate_item_meta_vport
   10990                 :            :                                 (key, vport_meta, priv->vport_meta_mask);
   10991                 :            :         } else {
   10992         [ #  # ]:          0 :                 flow_dv_translate_item_source_vport(key, id);
   10993                 :            :         }
   10994                 :            :         return 0;
   10995                 :            : }
   10996                 :            : 
   10997                 :            : /**
   10998                 :            :  * Translate port representor item to eswitch match on port id.
   10999                 :            :  *
   11000                 :            :  * @param[in] dev
   11001                 :            :  *   The devich to configure through.
   11002                 :            :  * @param[in, out] key
   11003                 :            :  *   Flow matcher value.
   11004                 :            :  * @param[in] key_type
   11005                 :            :  *   Set flow matcher mask or value.
   11006                 :            :  *
   11007                 :            :  * @return
   11008                 :            :  *   0 on success, a negative errno value otherwise.
   11009                 :            :  */
   11010                 :            : static int
   11011                 :          0 : flow_dv_translate_item_port_representor(struct rte_eth_dev *dev, void *key,
   11012                 :            :                                         uint32_t key_type)
   11013                 :            : {
   11014                 :          0 :         flow_dv_translate_item_source_vport(key,
   11015         [ #  # ]:          0 :                         key_type & MLX5_SET_MATCHER_V ?
   11016                 :          0 :                         mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   11017                 :          0 :         return 0;
   11018                 :            : }
   11019                 :            : 
   11020                 :            : /**
   11021                 :            :  * Translate represented port item to eswitch match on port id.
   11022                 :            :  *
   11023                 :            :  * @param[in] dev
   11024                 :            :  *   The devich to configure through.
   11025                 :            :  * @param[in, out] key
   11026                 :            :  *   Flow matcher value.
   11027                 :            :  * @param[in] item
   11028                 :            :  *   Flow pattern to translate.
   11029                 :            :  * @param[in]
   11030                 :            :  *   Flow attributes.
   11031                 :            :  *
   11032                 :            :  * @return
   11033                 :            :  *   0 on success, a negative errno value otherwise.
   11034                 :            :  */
   11035                 :            : static int
   11036                 :          0 : flow_dv_translate_item_represented_port(struct rte_eth_dev *dev, void *key,
   11037                 :            :                                         const struct rte_flow_item *item,
   11038                 :            :                                         const struct rte_flow_attr *attr,
   11039                 :            :                                         uint32_t key_type)
   11040                 :            : {
   11041         [ #  # ]:          0 :         const struct rte_flow_item_ethdev *pid_m = item ? item->mask : NULL;
   11042         [ #  # ]:          0 :         const struct rte_flow_item_ethdev *pid_v = item ? item->spec : NULL;
   11043                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   11044                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11045                 :            :         uint16_t mask, id;
   11046                 :            :         uint32_t vport_meta;
   11047                 :            :         bool vport_match = false;
   11048                 :            : 
   11049                 :            :         MLX5_ASSERT(wks);
   11050                 :            : #ifndef HAVE_IBV_DEVICE_ATTR_ESW_MGR_REG_C0
   11051         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
   11052                 :            :                 vport_match = true;
   11053                 :            : #endif
   11054         [ #  # ]:          0 :         if (!pid_m && !pid_v)
   11055                 :            :                 return 0;
   11056   [ #  #  #  # ]:          0 :         if (pid_v && pid_v->port_id == UINT16_MAX) {
   11057   [ #  #  #  # ]:          0 :                 if (priv->sh->config.dv_flow_en != 2 || vport_match) {
   11058                 :          0 :                         flow_dv_translate_item_source_vport
   11059         [ #  # ]:          0 :                                 (key, key_type & MLX5_SET_MATCHER_V ?
   11060                 :          0 :                                  mlx5_flow_get_esw_manager_vport_id(dev) : 0xffff);
   11061                 :            :                 } else {
   11062         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   11063                 :          0 :                                 vport_meta = priv->sh->dev_cap.esw_info.regc_mask;
   11064                 :            :                         else
   11065                 :          0 :                                 vport_meta = priv->sh->dev_cap.esw_info.regc_value;
   11066                 :          0 :                         flow_dv_translate_item_meta_vport(key, vport_meta,
   11067                 :            :                                                           priv->sh->dev_cap.esw_info.regc_mask);
   11068                 :            :                 }
   11069                 :          0 :                 return 0;
   11070                 :            :         }
   11071         [ #  # ]:          0 :         mask = pid_m ? pid_m->port_id : UINT16_MAX;
   11072         [ #  # ]:          0 :         id = pid_v ? pid_v->port_id : dev->data->port_id;
   11073                 :          0 :         priv = mlx5_port_to_eswitch_info(id, item == NULL);
   11074         [ #  # ]:          0 :         if (!priv)
   11075                 :          0 :                 return -rte_errno;
   11076         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   11077                 :            :                 id = mask;
   11078                 :          0 :                 vport_meta = priv->vport_meta_mask;
   11079                 :            :         } else {
   11080                 :          0 :                 id = priv->vport_id;
   11081                 :          0 :                 vport_meta = priv->vport_meta_tag;
   11082                 :          0 :                 wks->vport_meta_tag = vport_meta;
   11083                 :            :         }
   11084                 :            :         /*
   11085                 :            :          * Translate to vport field or to metadata, depending on mode.
   11086                 :            :          * Kernel can use either misc.source_port or half of C0 metadata
   11087                 :            :          * register.
   11088                 :            :          */
   11089   [ #  #  #  # ]:          0 :         if (priv->vport_meta_mask && !vport_match) {
   11090                 :            :                 /*
   11091                 :            :                  * Provide the hint for SW steering library
   11092                 :            :                  * to insert the flow into ingress domain and
   11093                 :            :                  * save the extra vport match.
   11094                 :            :                  */
   11095   [ #  #  #  # ]:          0 :                 if (mask == UINT16_MAX && priv->vport_id == UINT16_MAX &&
   11096   [ #  #  #  # ]:          0 :                     priv->pf_bond < 0 && attr->transfer &&
   11097         [ #  # ]:          0 :                     priv->sh->config.dv_flow_en != 2)
   11098         [ #  # ]:          0 :                         flow_dv_translate_item_source_vport(key, id);
   11099                 :            :                 /*
   11100                 :            :                  * We should always set the vport metadata register,
   11101                 :            :                  * otherwise the SW steering library can drop
   11102                 :            :                  * the rule if wire vport metadata value is not zero,
   11103                 :            :                  * it depends on kernel configuration.
   11104                 :            :                  */
   11105                 :          0 :                 flow_dv_translate_item_meta_vport(key, vport_meta,
   11106                 :            :                                                   priv->vport_meta_mask);
   11107                 :            :         } else {
   11108         [ #  # ]:          0 :                 flow_dv_translate_item_source_vport(key, id);
   11109                 :            :         }
   11110                 :            :         return 0;
   11111                 :            : }
   11112                 :            : 
   11113                 :            : /**
   11114                 :            :  * Translate port-id item to eswitch match on  port-id.
   11115                 :            :  *
   11116                 :            :  * @param[in] dev
   11117                 :            :  *   The devich to configure through.
   11118                 :            :  * @param[in, out] matcher
   11119                 :            :  *   Flow matcher.
   11120                 :            :  * @param[in, out] key
   11121                 :            :  *   Flow matcher value.
   11122                 :            :  * @param[in] item
   11123                 :            :  *   Flow pattern to translate.
   11124                 :            :  * @param[in] attr
   11125                 :            :  *   Flow attributes.
   11126                 :            :  *
   11127                 :            :  * @return
   11128                 :            :  *   0 on success, a negative errno value otherwise.
   11129                 :            :  */
   11130                 :            : static int
   11131                 :          0 : flow_dv_translate_item_port_id_all(struct rte_eth_dev *dev,
   11132                 :            :                                void *matcher, void *key,
   11133                 :            :                                const struct rte_flow_item *item,
   11134                 :            :                                const struct rte_flow_attr *attr)
   11135                 :            : {
   11136                 :            :         int ret;
   11137                 :            : 
   11138                 :          0 :         ret = flow_dv_translate_item_port_id
   11139                 :            :                         (dev, matcher, item, attr, MLX5_SET_MATCHER_SW_M);
   11140         [ #  # ]:          0 :         if (ret)
   11141                 :            :                 return ret;
   11142                 :          0 :         ret = flow_dv_translate_item_port_id
   11143                 :            :                         (dev, key, item, attr, MLX5_SET_MATCHER_SW_V);
   11144                 :          0 :         return ret;
   11145                 :            : }
   11146                 :            : 
   11147                 :            : 
   11148                 :            : /**
   11149                 :            :  * Add ICMP6 item to the value.
   11150                 :            :  *
   11151                 :            :  * @param[in, out] key
   11152                 :            :  *   Flow matcher value.
   11153                 :            :  * @param[in] item
   11154                 :            :  *   Flow pattern to translate.
   11155                 :            :  * @param[in] inner
   11156                 :            :  *   Item is inner pattern.
   11157                 :            :  * @param[in] key_type
   11158                 :            :  *   Set flow matcher mask or value.
   11159                 :            :  */
   11160                 :            : static void
   11161                 :          0 : flow_dv_translate_item_icmp6(void *key, const struct rte_flow_item *item,
   11162                 :            :                              int inner, uint32_t key_type)
   11163                 :            : {
   11164                 :            :         const struct rte_flow_item_icmp6 *icmp6_m;
   11165                 :            :         const struct rte_flow_item_icmp6 *icmp6_v;
   11166                 :            :         void *headers_v;
   11167                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11168                 :            : 
   11169         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11170                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11171         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11172         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xFF);
   11173                 :            :         else
   11174         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
   11175                 :            :                          IPPROTO_ICMPV6);
   11176   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11177                 :            :                 return;
   11178   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp6_v, icmp6_m,
             #  #  #  # ]
   11179                 :            :                 &rte_flow_item_icmp6_mask);
   11180         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type,
   11181                 :            :                  icmp6_v->type & icmp6_m->type);
   11182         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code,
   11183                 :            :                  icmp6_v->code & icmp6_m->code);
   11184                 :            : }
   11185                 :            : 
   11186                 :            : /**
   11187                 :            :  * Add ICMP6 echo request/reply item to the value.
   11188                 :            :  *
   11189                 :            :  * @param[in, out] key
   11190                 :            :  *   Flow matcher value.
   11191                 :            :  * @param[in] item
   11192                 :            :  *   Flow pattern to translate.
   11193                 :            :  * @param[in] inner
   11194                 :            :  *   Item is inner pattern.
   11195                 :            :  * @param[in] key_type
   11196                 :            :  *   Set flow matcher mask or value.
   11197                 :            :  */
   11198                 :            : static void
   11199         [ #  # ]:          0 : flow_dv_translate_item_icmp6_echo(void *key, const struct rte_flow_item *item,
   11200                 :            :                                   int inner, uint32_t key_type)
   11201                 :            : {
   11202                 :            :         const struct rte_flow_item_icmp6_echo *icmp6_m;
   11203                 :            :         const struct rte_flow_item_icmp6_echo *icmp6_v;
   11204                 :            :         uint32_t icmp6_header_data_m = 0;
   11205                 :            :         uint32_t icmp6_header_data_v = 0;
   11206                 :            :         void *headers_v;
   11207                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11208                 :            :         uint8_t icmp6_type = 0;
   11209                 :            :         struct rte_flow_item_icmp6_echo zero_mask;
   11210                 :            : 
   11211                 :            :         memset(&zero_mask, 0, sizeof(zero_mask));
   11212         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11213                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11214         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11215         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 0xFF);
   11216                 :            :         else
   11217         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
   11218                 :            :                          IPPROTO_ICMPV6);
   11219   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp6_v, icmp6_m, &zero_mask);
             #  #  #  # ]
   11220                 :            :         /* Set fixed type and code for icmpv6 echo request or reply */
   11221         [ #  # ]:          0 :         icmp6_type = (item->type == RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST ?
   11222                 :            :                       RTE_ICMP6_ECHO_REQUEST : RTE_ICMP6_ECHO_REPLY);
   11223         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M) {
   11224         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, 0xFF);
   11225         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 0xFF);
   11226                 :            :         } else {
   11227         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, icmp6_type);
   11228         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 0);
   11229                 :            :         }
   11230         [ #  # ]:          0 :         if (icmp6_v == NULL)
   11231                 :          0 :                 return;
   11232                 :            :         /* Set icmp6 header data (identifier & sequence) accordingly */
   11233                 :          0 :         icmp6_header_data_m =
   11234         [ #  # ]:          0 :                 (rte_be_to_cpu_16(icmp6_m->hdr.identifier) << 16) |
   11235         [ #  # ]:          0 :                 rte_be_to_cpu_16(icmp6_m->hdr.sequence);
   11236         [ #  # ]:          0 :         if (icmp6_header_data_m) {
   11237                 :          0 :                 icmp6_header_data_v =
   11238         [ #  # ]:          0 :                         (rte_be_to_cpu_16(icmp6_v->hdr.identifier) << 16) |
   11239         [ #  # ]:          0 :                         rte_be_to_cpu_16(icmp6_v->hdr.sequence);
   11240         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_header_data,
   11241                 :            :                          icmp6_header_data_v & icmp6_header_data_m);
   11242                 :            :         }
   11243                 :            : }
   11244                 :            : 
   11245                 :            : /**
   11246                 :            :  * Add ICMP item to the value.
   11247                 :            :  *
   11248                 :            :  * @param[in, out] key
   11249                 :            :  *   Flow matcher value.
   11250                 :            :  * @param[in] item
   11251                 :            :  *   Flow pattern to translate.
   11252                 :            :  * @param[in] inner
   11253                 :            :  *   Item is inner pattern.
   11254                 :            :  * @param[in] key_type
   11255                 :            :  *   Set flow matcher mask or value.
   11256                 :            :  */
   11257                 :            : static void
   11258                 :          0 : flow_dv_translate_item_icmp(void *key, const struct rte_flow_item *item,
   11259                 :            :                             int inner, uint32_t key_type)
   11260                 :            : {
   11261                 :            :         const struct rte_flow_item_icmp *icmp_m;
   11262                 :            :         const struct rte_flow_item_icmp *icmp_v;
   11263                 :            :         uint32_t icmp_header_data_m = 0;
   11264                 :            :         uint32_t icmp_header_data_v = 0;
   11265                 :            :         void *headers_v;
   11266                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11267                 :            : 
   11268         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11269                 :            :                         MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11270         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11271         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11272                 :            :                          ip_protocol, 0xFF);
   11273                 :            :         else
   11274         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11275                 :            :                          ip_protocol, IPPROTO_ICMP);
   11276   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11277                 :            :                 return;
   11278   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, icmp_v, icmp_m,
             #  #  #  # ]
   11279                 :            :                 &rte_flow_item_icmp_mask);
   11280         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmp_type,
   11281                 :            :                  icmp_v->hdr.icmp_type & icmp_m->hdr.icmp_type);
   11282         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, icmp_code,
   11283                 :            :                  icmp_v->hdr.icmp_code & icmp_m->hdr.icmp_code);
   11284         [ #  # ]:          0 :         icmp_header_data_m = rte_be_to_cpu_16(icmp_m->hdr.icmp_seq_nb);
   11285         [ #  # ]:          0 :         icmp_header_data_m |= rte_be_to_cpu_16(icmp_m->hdr.icmp_ident) << 16;
   11286         [ #  # ]:          0 :         if (icmp_header_data_m) {
   11287         [ #  # ]:          0 :                 icmp_header_data_v = rte_be_to_cpu_16(icmp_v->hdr.icmp_seq_nb);
   11288                 :          0 :                 icmp_header_data_v |=
   11289         [ #  # ]:          0 :                          rte_be_to_cpu_16(icmp_v->hdr.icmp_ident) << 16;
   11290         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_misc3, misc3_v, icmp_header_data,
   11291                 :            :                          icmp_header_data_v & icmp_header_data_m);
   11292                 :            :         }
   11293                 :            : }
   11294                 :            : 
   11295                 :            : /**
   11296                 :            :  * Add GTP item to the value.
   11297                 :            :  *
   11298                 :            :  * @param[in, out] key
   11299                 :            :  *   Flow matcher value.
   11300                 :            :  * @param[in] item
   11301                 :            :  *   Flow pattern to translate.
   11302                 :            :  * @param[in] inner
   11303                 :            :  *   Item is inner pattern.
   11304                 :            :  * @param[in] key_type
   11305                 :            :  *   Set flow matcher mask or value.
   11306                 :            :  */
   11307                 :            : static void
   11308                 :          0 : flow_dv_translate_item_gtp(void *key, const struct rte_flow_item *item,
   11309                 :            :                            int inner, uint32_t key_type)
   11310                 :            : {
   11311                 :            :         const struct rte_flow_item_gtp *gtp_m;
   11312                 :            :         const struct rte_flow_item_gtp *gtp_v;
   11313                 :            :         void *headers_v;
   11314                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11315                 :            :         uint16_t dport = RTE_GTPU_UDP_PORT;
   11316                 :            : 
   11317         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11318                 :            :                         MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11319   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   11320         [ #  # ]:          0 :                 if (key_type & MLX5_SET_MATCHER_M)
   11321         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11322                 :            :                                  udp_dport, 0xFFFF);
   11323                 :            :                 else
   11324         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers_v,
   11325                 :            :                                  udp_dport, dport);
   11326                 :            :         }
   11327   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11328                 :            :                 return;
   11329   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, gtp_v, gtp_m,
             #  #  #  # ]
   11330                 :            :                 &rte_flow_item_gtp_mask);
   11331         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags,
   11332                 :            :                  gtp_v->hdr.gtp_hdr_info & gtp_m->hdr.gtp_hdr_info);
   11333         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_type,
   11334                 :            :                  gtp_v->hdr.msg_type & gtp_m->hdr.msg_type);
   11335   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_teid,
   11336                 :            :                  rte_be_to_cpu_32(gtp_v->hdr.teid & gtp_m->hdr.teid));
   11337                 :            : }
   11338                 :            : 
   11339                 :            : /**
   11340                 :            :  * Add GTP PSC item to matcher.
   11341                 :            :  *
   11342                 :            :  * @param[in, out] key
   11343                 :            :  *   Flow matcher value.
   11344                 :            :  * @param[in] item
   11345                 :            :  *   Flow pattern to translate.
   11346                 :            :  * @param[in] key_type
   11347                 :            :  *   Set flow matcher mask or value.
   11348                 :            :  */
   11349                 :            : static int
   11350                 :          0 : flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
   11351                 :            :                                uint32_t key_type)
   11352                 :            : {
   11353                 :            :         const struct rte_flow_item_gtp_psc *gtp_psc_m;
   11354                 :            :         const struct rte_flow_item_gtp_psc *gtp_psc_v;
   11355                 :            :         void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
   11356                 :            :         union {
   11357                 :            :                 uint32_t w32;
   11358                 :            :                 struct {
   11359                 :            :                         uint16_t seq_num;
   11360                 :            :                         uint8_t npdu_num;
   11361                 :            :                         uint8_t next_ext_header_type;
   11362                 :            :                 };
   11363                 :            :         } dw_2;
   11364                 :            :         union {
   11365                 :            :                 uint32_t w32;
   11366                 :            :                 struct {
   11367                 :            :                         uint8_t len;
   11368                 :            :                         uint8_t type_flags;
   11369                 :            :                         uint8_t qfi;
   11370                 :            :                         uint8_t reserved;
   11371                 :            :                 };
   11372                 :            :         } dw_0;
   11373                 :            :         uint8_t gtp_flags;
   11374                 :            : 
   11375                 :            :         /* Always set E-flag match on one, regardless of GTP item settings. */
   11376         [ #  # ]:          0 :         gtp_flags = MLX5_GET(fte_match_set_misc3, misc3_v, gtpu_msg_flags);
   11377                 :          0 :         gtp_flags |= MLX5_GTP_EXT_HEADER_FLAG;
   11378         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags, gtp_flags);
   11379                 :            :         /*Set next extension header type. */
   11380                 :          0 :         dw_2.seq_num = 0;
   11381                 :          0 :         dw_2.npdu_num = 0;
   11382         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_M)
   11383                 :          0 :                 dw_2.next_ext_header_type = 0xff;
   11384                 :            :         else
   11385                 :          0 :                 dw_2.next_ext_header_type = 0x85;
   11386   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_dw_2,
   11387                 :            :                  rte_cpu_to_be_32(dw_2.w32));
   11388   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11389                 :            :                 return 0;
   11390   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, gtp_psc_v,
             #  #  #  # ]
   11391                 :            :                 gtp_psc_m, &rte_flow_item_gtp_psc_mask);
   11392                 :          0 :         dw_0.w32 = 0;
   11393                 :          0 :         dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->hdr.type &
   11394                 :            :                                                   gtp_psc_m->hdr.type);
   11395                 :          0 :         dw_0.qfi = gtp_psc_v->hdr.qfi & gtp_psc_m->hdr.qfi;
   11396   [ #  #  #  # ]:          0 :         MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_first_ext_dw_0,
   11397                 :            :                  rte_cpu_to_be_32(dw_0.w32));
   11398                 :          0 :         return 0;
   11399                 :            : }
   11400                 :            : 
   11401                 :            : /**
   11402                 :            :  * Add eCPRI item to matcher and to the value.
   11403                 :            :  *
   11404                 :            :  * @param[in] dev
   11405                 :            :  *   The devich to configure through.
   11406                 :            :  * @param[in, out] key
   11407                 :            :  *   Flow matcher value.
   11408                 :            :  * @param[in] item
   11409                 :            :  *   Flow pattern to translate.
   11410                 :            :  * @param[in] last_item
   11411                 :            :  *   Last item flags.
   11412                 :            :  * @param[in] key_type
   11413                 :            :  *   Set flow matcher mask or value.
   11414                 :            :  */
   11415                 :            : static void
   11416                 :          0 : flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
   11417                 :            :                              const struct rte_flow_item *item,
   11418                 :            :                              uint64_t last_item, uint32_t key_type)
   11419                 :            : {
   11420                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11421                 :            :         const struct rte_flow_item_ecpri *ecpri_m;
   11422                 :            :         const struct rte_flow_item_ecpri *ecpri_v;
   11423                 :          0 :         const struct rte_flow_item_ecpri *ecpri_vv = item->spec;
   11424                 :            :         struct rte_ecpri_common_hdr common;
   11425                 :            :         void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4);
   11426                 :            :         uint32_t *samples;
   11427                 :            :         void *dw_v;
   11428                 :            : 
   11429                 :            :         /*
   11430                 :            :          * In case of eCPRI over Ethernet, if EtherType is not specified,
   11431                 :            :          * match on eCPRI EtherType implicitly.
   11432                 :            :          */
   11433         [ #  # ]:          0 :         if (last_item & MLX5_FLOW_LAYER_OUTER_L2) {
   11434                 :            :                 void *hdrs_v, *l2v;
   11435                 :            : 
   11436                 :            :                 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11437                 :            :                 l2v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
   11438         [ #  # ]:          0 :                 if (*(uint16_t *)l2v == 0) {
   11439         [ #  # ]:          0 :                         if (key_type & MLX5_SET_MATCHER_M)
   11440                 :          0 :                                 *(uint16_t *)l2v = UINT16_MAX;
   11441                 :            :                         else
   11442                 :          0 :                                 *(uint16_t *)l2v =
   11443                 :            :                                         RTE_BE16(RTE_ETHER_TYPE_ECPRI);
   11444                 :            :                 }
   11445                 :            :         }
   11446   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11447                 :          0 :                 return;
   11448   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m,
             #  #  #  # ]
   11449                 :            :                 &rte_flow_item_ecpri_mask);
   11450                 :            :         /*
   11451                 :            :          * Maximal four DW samples are supported in a single matching now.
   11452                 :            :          * Two are used now for a eCPRI matching:
   11453                 :            :          * 1. Type: one byte, mask should be 0x00ff0000 in network order
   11454                 :            :          * 2. ID of a message: one or two bytes, mask 0xffff0000 or 0xff000000
   11455                 :            :          *    if any.
   11456                 :            :          */
   11457         [ #  # ]:          0 :         if (!ecpri_m->hdr.common.u32)
   11458                 :            :                 return;
   11459                 :          0 :         samples = priv->sh->ecpri_parser.ids;
   11460                 :            :         /* Need to take the whole DW as the mask to fill the entry. */
   11461                 :            :         dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
   11462                 :            :                             prog_sample_field_value_0);
   11463                 :            :         /* Already big endian (network order) in the header. */
   11464                 :          0 :         *(uint32_t *)dw_v = ecpri_v->hdr.common.u32 & ecpri_m->hdr.common.u32;
   11465                 :            :         /* Sample#0, used for matching type, offset 0. */
   11466                 :            :         /* It makes no sense to set the sample ID in the mask field. */
   11467         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc4, misc4_v,
   11468                 :            :                  prog_sample_field_id_0, samples[0]);
   11469                 :            :         /*
   11470                 :            :          * Checking if message body part needs to be matched.
   11471                 :            :          * Some wildcard rules only matching type field should be supported.
   11472                 :            :          */
   11473         [ #  # ]:          0 :         if (ecpri_m->hdr.dummy[0]) {
   11474         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_M)
   11475         [ #  # ]:          0 :                         common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
   11476                 :            :                 else
   11477         [ #  # ]:          0 :                         common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
   11478         [ #  # ]:          0 :                 switch (common.type) {
   11479                 :          0 :                 case RTE_ECPRI_MSG_TYPE_IQ_DATA:
   11480                 :            :                 case RTE_ECPRI_MSG_TYPE_RTC_CTRL:
   11481                 :            :                 case RTE_ECPRI_MSG_TYPE_DLY_MSR:
   11482                 :            :                         dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
   11483                 :            :                                             prog_sample_field_value_1);
   11484                 :          0 :                         *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] &
   11485                 :            :                                             ecpri_m->hdr.dummy[0];
   11486                 :            :                         /* Sample#1, to match message body, offset 4. */
   11487         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_misc4, misc4_v,
   11488                 :            :                                  prog_sample_field_id_1, samples[1]);
   11489                 :          0 :                         break;
   11490                 :            :                 default:
   11491                 :            :                         /* Others, do not match any sample ID. */
   11492                 :            :                         break;
   11493                 :            :                 }
   11494                 :            :         }
   11495                 :            : }
   11496                 :            : 
   11497                 :            : /*
   11498                 :            :  * Add connection tracking status item to matcher
   11499                 :            :  *
   11500                 :            :  * @param[in] dev
   11501                 :            :  *   The devich to configure through.
   11502                 :            :  * @param[in, out] matcher
   11503                 :            :  *   Flow matcher.
   11504                 :            :  * @param[in, out] key
   11505                 :            :  *   Flow matcher value.
   11506                 :            :  * @param[in] item
   11507                 :            :  *   Flow pattern to translate.
   11508                 :            :  */
   11509                 :            : static void
   11510                 :          0 : flow_dv_translate_item_aso_ct(struct rte_eth_dev *dev,
   11511                 :            :                               void *matcher, void *key,
   11512                 :            :                               const struct rte_flow_item *item)
   11513                 :            : {
   11514                 :            :         uint32_t reg_value = 0;
   11515                 :            :         int reg_id;
   11516                 :            :         /* 8LSB 0b 11/0000/11, middle 4 bits are reserved. */
   11517                 :            :         uint32_t reg_mask = 0;
   11518                 :          0 :         const struct rte_flow_item_conntrack *spec = item->spec;
   11519                 :          0 :         const struct rte_flow_item_conntrack *mask = item->mask;
   11520                 :            :         uint32_t flags;
   11521                 :            :         struct rte_flow_error error;
   11522                 :            : 
   11523         [ #  # ]:          0 :         if (!mask)
   11524                 :            :                 mask = &rte_flow_item_conntrack_mask;
   11525   [ #  #  #  # ]:          0 :         if (!spec || !mask->flags)
   11526                 :          0 :                 return;
   11527                 :          0 :         flags = spec->flags & mask->flags;
   11528                 :            :         /* The conflict should be checked in the validation. */
   11529                 :            :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_VALID)
   11530                 :            :                 reg_value |= MLX5_CT_SYNDROME_VALID;
   11531         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
   11532                 :            :                 reg_value |= MLX5_CT_SYNDROME_STATE_CHANGE;
   11533         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_INVALID)
   11534                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_INVALID;
   11535         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED)
   11536                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_TRAP;
   11537         [ #  # ]:          0 :         if (flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
   11538                 :          0 :                 reg_value |= MLX5_CT_SYNDROME_BAD_PACKET;
   11539         [ #  # ]:          0 :         if (mask->flags & (RTE_FLOW_CONNTRACK_PKT_STATE_VALID |
   11540                 :            :                            RTE_FLOW_CONNTRACK_PKT_STATE_INVALID |
   11541                 :            :                            RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED))
   11542                 :            :                 reg_mask |= 0xc0;
   11543         [ #  # ]:          0 :         if (mask->flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
   11544                 :          0 :                 reg_mask |= MLX5_CT_SYNDROME_STATE_CHANGE;
   11545         [ #  # ]:          0 :         if (mask->flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
   11546                 :          0 :                 reg_mask |= MLX5_CT_SYNDROME_BAD_PACKET;
   11547                 :            :         /* The REG_C_x value could be saved during startup. */
   11548                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, &error);
   11549         [ #  # ]:          0 :         if (reg_id == REG_NON)
   11550                 :            :                 return;
   11551                 :          0 :         flow_dv_match_meta_reg_all(matcher, key, (enum modify_reg)reg_id,
   11552                 :            :                                reg_value, reg_mask);
   11553                 :            : }
   11554                 :            : 
   11555                 :            : static void
   11556                 :          0 : flow_dv_translate_item_flex(struct rte_eth_dev *dev, void *matcher, void *key,
   11557                 :            :                             const struct rte_flow_item *item,
   11558                 :            :                             struct mlx5_flow *dev_flow, bool is_inner)
   11559                 :            : {
   11560                 :          0 :         const struct rte_flow_item_flex *spec =
   11561                 :            :                 (const struct rte_flow_item_flex *)item->spec;
   11562                 :          0 :         int index = mlx5_flex_acquire_index(dev, spec->handle, false);
   11563                 :            : 
   11564                 :            :         MLX5_ASSERT(index >= 0 && index < (int)(sizeof(uint32_t) * CHAR_BIT));
   11565         [ #  # ]:          0 :         if (index < 0)
   11566                 :            :                 return;
   11567         [ #  # ]:          0 :         if (!(dev_flow->handle->flex_item & RTE_BIT32(index))) {
   11568                 :            :                 /* Don't count both inner and outer flex items in one rule. */
   11569                 :          0 :                 if (mlx5_flex_acquire_index(dev, spec->handle, true) != index)
   11570                 :            :                         MLX5_ASSERT(false);
   11571                 :          0 :                 dev_flow->handle->flex_item |= (uint8_t)RTE_BIT32(index);
   11572                 :            :         }
   11573                 :          0 :         mlx5_flex_flow_translate_item(dev, matcher, key, item, is_inner);
   11574                 :            : }
   11575                 :            : 
   11576                 :            : /**
   11577                 :            :  * Add METER_COLOR item to matcher
   11578                 :            :  *
   11579                 :            :  * @param[in] dev
   11580                 :            :  *   The device to configure through.
   11581                 :            :  * @param[in, out] key
   11582                 :            :  *   Flow matcher value.
   11583                 :            :  * @param[in] item
   11584                 :            :  *   Flow pattern to translate.
   11585                 :            :  * @param[in] key_type
   11586                 :            :  *   Set flow matcher mask or value.
   11587                 :            :  */
   11588                 :            : static void
   11589                 :          0 : flow_dv_translate_item_meter_color(struct rte_eth_dev *dev, void *key,
   11590                 :            :                             const struct rte_flow_item *item,
   11591                 :            :                             uint32_t key_type)
   11592                 :            : {
   11593                 :          0 :         const struct rte_flow_item_meter_color *color_m = item->mask;
   11594                 :          0 :         const struct rte_flow_item_meter_color *color_v = item->spec;
   11595                 :            :         uint32_t value, mask;
   11596                 :            :         int reg = REG_NON;
   11597                 :            : 
   11598                 :            :         MLX5_ASSERT(color_v);
   11599   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11600                 :            :                 return;
   11601   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, color_v, color_m,
             #  #  #  # ]
   11602                 :            :                 &rte_flow_item_meter_color_mask);
   11603         [ #  # ]:          0 :         value = rte_col_2_mlx5_col(color_v->color);
   11604                 :            :         mask = color_m ?
   11605         [ #  # ]:          0 :                 color_m->color : (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
   11606         [ #  # ]:          0 :         if (!!(key_type & MLX5_SET_MATCHER_SW))
   11607                 :          0 :                 reg = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
   11608                 :            :         else
   11609                 :            :                 reg = flow_hw_get_reg_id(dev,
   11610                 :            :                                          RTE_FLOW_ITEM_TYPE_METER_COLOR, 0);
   11611         [ #  # ]:          0 :         if (reg == REG_NON)
   11612                 :            :                 return;
   11613                 :          0 :         flow_dv_match_meta_reg(key, (enum modify_reg)reg, value, mask);
   11614                 :            : }
   11615                 :            : 
   11616                 :            : static void
   11617                 :          0 : flow_dv_translate_item_aggr_affinity(void *key,
   11618                 :            :                                     const struct rte_flow_item *item,
   11619                 :            :                                     uint32_t key_type)
   11620                 :            : {
   11621                 :            :         const struct rte_flow_item_aggr_affinity *affinity_v;
   11622                 :            :         const struct rte_flow_item_aggr_affinity *affinity_m;
   11623                 :            :         void *misc_v;
   11624                 :            : 
   11625   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, affinity_v, affinity_m,
             #  #  #  # ]
   11626                 :            :                          &rte_flow_item_aggr_affinity_mask);
   11627                 :            :         misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   11628         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, lag_rx_port_affinity,
   11629                 :            :                  affinity_v->affinity & affinity_m->affinity);
   11630                 :          0 : }
   11631                 :            : 
   11632                 :            : static void
   11633                 :          0 : flow_dv_translate_item_ib_bth(void *key,
   11634                 :            :                               const struct rte_flow_item *item,
   11635                 :            :                               int inner, uint32_t key_type)
   11636                 :            : {
   11637                 :            :         const struct rte_flow_item_ib_bth *bth_m;
   11638                 :            :         const struct rte_flow_item_ib_bth *bth_v;
   11639                 :            :         void *headers_v, *misc_v;
   11640                 :            :         uint16_t udp_dport;
   11641                 :            :         char *qpn_v;
   11642                 :            :         int i, size;
   11643                 :            : 
   11644         [ #  # ]:          0 :         headers_v = inner ? MLX5_ADDR_OF(fte_match_param, key, inner_headers) :
   11645                 :            :                 MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   11646   [ #  #  #  # ]:          0 :         if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
   11647         [ #  # ]:          0 :                 udp_dport = key_type & MLX5_SET_MATCHER_M ?
   11648                 :            :                         0xFFFF : MLX5_UDP_PORT_ROCEv2;
   11649         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, udp_dport);
   11650                 :            :         }
   11651   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(item, key_type))
          #  #  #  #  #  
                      # ]
   11652                 :            :                 return;
   11653   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, bth_v, bth_m, &rte_flow_item_ib_bth_mask);
             #  #  #  # ]
   11654                 :            :         misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   11655         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, bth_opcode,
   11656                 :            :                  bth_v->hdr.opcode & bth_m->hdr.opcode);
   11657                 :          0 :         qpn_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, bth_dst_qp);
   11658                 :            :         size = sizeof(bth_m->hdr.dst_qp);
   11659         [ #  # ]:          0 :         for (i = 0; i < size; ++i)
   11660                 :          0 :                 qpn_v[i] = bth_m->hdr.dst_qp[i] & bth_v->hdr.dst_qp[i];
   11661                 :            : }
   11662                 :            : 
   11663                 :            : static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
   11664                 :            : 
   11665                 :            : #define HEADER_IS_ZERO(match_criteria, headers)                              \
   11666                 :            :         !(memcmp(MLX5_ADDR_OF(fte_match_param, match_criteria, headers),     \
   11667                 :            :                  matcher_zero, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \
   11668                 :            : 
   11669                 :            : /**
   11670                 :            :  * Calculate flow matcher enable bitmap.
   11671                 :            :  *
   11672                 :            :  * @param match_criteria
   11673                 :            :  *   Pointer to flow matcher criteria.
   11674                 :            :  *
   11675                 :            :  * @return
   11676                 :            :  *   Bitmap of enabled fields.
   11677                 :            :  */
   11678                 :            : static uint8_t
   11679                 :          0 : flow_dv_matcher_enable(uint32_t *match_criteria)
   11680                 :            : {
   11681                 :            :         uint8_t match_criteria_enable;
   11682                 :            : 
   11683                 :            :         match_criteria_enable =
   11684                 :          0 :                 (!HEADER_IS_ZERO(match_criteria, outer_headers)) <<
   11685                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_OUTER_BIT;
   11686                 :          0 :         match_criteria_enable |=
   11687         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters)) <<
   11688                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC_BIT;
   11689                 :          0 :         match_criteria_enable |=
   11690         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, inner_headers)) <<
   11691                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_INNER_BIT;
   11692                 :          0 :         match_criteria_enable |=
   11693         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) <<
   11694                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT;
   11695                 :          0 :         match_criteria_enable |=
   11696         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_3)) <<
   11697                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC3_BIT;
   11698                 :          0 :         match_criteria_enable |=
   11699         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_4)) <<
   11700                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT;
   11701                 :          0 :         match_criteria_enable |=
   11702         [ #  # ]:          0 :                 (!HEADER_IS_ZERO(match_criteria, misc_parameters_5)) <<
   11703                 :            :                 MLX5_MATCH_CRITERIA_ENABLE_MISC5_BIT;
   11704                 :          0 :         return match_criteria_enable;
   11705                 :            : }
   11706                 :            : 
   11707                 :            : static void
   11708                 :            : __flow_dv_adjust_buf_size(size_t *size, uint8_t match_criteria)
   11709                 :            : {
   11710                 :            :         /*
   11711                 :            :          * Check flow matching criteria first, subtract misc5/4 length if flow
   11712                 :            :          * doesn't own misc5/4 parameters. In some old rdma-core releases,
   11713                 :            :          * misc5/4 are not supported, and matcher creation failure is expected
   11714                 :            :          * w/o subtraction. If misc5 is provided, misc4 must be counted in since
   11715                 :            :          * misc5 is right after misc4.
   11716                 :            :          */
   11717                 :          0 :         if (!(match_criteria & (1 << MLX5_MATCH_CRITERIA_ENABLE_MISC5_BIT))) {
   11718                 :          0 :                 *size = MLX5_ST_SZ_BYTES(fte_match_param) -
   11719                 :            :                         MLX5_ST_SZ_BYTES(fte_match_set_misc5);
   11720   [ #  #  #  #  :          0 :                 if (!(match_criteria & (1 <<
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
   11721                 :            :                         MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT))) {
   11722                 :          0 :                         *size -= MLX5_ST_SZ_BYTES(fte_match_set_misc4);
   11723                 :            :                 }
   11724                 :            :         }
   11725                 :            : }
   11726                 :            : 
   11727                 :            : struct mlx5_list_entry *
   11728                 :          0 : mlx5_flow_matcher_clone_cb(void *tool_ctx __rte_unused,
   11729                 :            :                            struct mlx5_list_entry *entry, void *cb_ctx)
   11730                 :            : {
   11731                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11732                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   11733                 :            :         struct mlx5_flow_dv_matcher *old_resource;
   11734                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(ref->tbl,
   11735                 :            :                                                             typeof(*tbl), tbl);
   11736                 :          0 :         struct mlx5_flow_dv_matcher *resource = mlx5_malloc(MLX5_MEM_ANY,
   11737                 :            :                                                             sizeof(*resource),
   11738                 :            :                                                             0, SOCKET_ID_ANY);
   11739                 :            : 
   11740         [ #  # ]:          0 :         if (!resource) {
   11741                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   11742                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11743                 :            :                                    "cannot create matcher");
   11744                 :          0 :                 return NULL;
   11745                 :            :         }
   11746                 :            :         old_resource = container_of(entry, typeof(*old_resource), entry);
   11747                 :            :         memcpy(resource, old_resource, sizeof(*resource));
   11748                 :          0 :         resource->tbl = &tbl->tbl;
   11749                 :          0 :         return &resource->entry;
   11750                 :            : }
   11751                 :            : 
   11752                 :            : void
   11753                 :          0 : mlx5_flow_matcher_clone_free_cb(void *tool_ctx __rte_unused,
   11754                 :            :                                 struct mlx5_list_entry *entry)
   11755                 :            : {
   11756                 :          0 :         mlx5_free(entry);
   11757                 :          0 : }
   11758                 :            : 
   11759                 :            : struct mlx5_list_entry *
   11760                 :          0 : mlx5_flow_dv_tbl_create_cb(void *tool_ctx, void *cb_ctx)
   11761                 :            : {
   11762                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11763                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11764                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   11765                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11766                 :          0 :         struct mlx5_flow_tbl_tunnel_prm *tt_prm = ctx->data2;
   11767                 :          0 :         struct rte_flow_error *error = ctx->error;
   11768                 :          0 :         union mlx5_flow_tbl_key key = { .v64 = *(uint64_t *)(ctx->data) };
   11769                 :            :         struct mlx5_flow_tbl_resource *tbl;
   11770                 :            :         void *domain;
   11771                 :          0 :         uint32_t idx = 0;
   11772                 :            :         int ret;
   11773                 :            : 
   11774                 :          0 :         tbl_data = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_JUMP], &idx);
   11775         [ #  # ]:          0 :         if (!tbl_data) {
   11776                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11777                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11778                 :            :                                    NULL,
   11779                 :            :                                    "cannot allocate flow table data entry");
   11780                 :          0 :                 return NULL;
   11781                 :            :         }
   11782                 :          0 :         tbl_data->idx = idx;
   11783                 :          0 :         tbl_data->tunnel = tt_prm->tunnel;
   11784                 :          0 :         tbl_data->group_id = tt_prm->group_id;
   11785         [ #  # ]:          0 :         tbl_data->external = !!tt_prm->external;
   11786                 :          0 :         tbl_data->tunnel_offload = is_tunnel_offload_active(dev);
   11787                 :          0 :         tbl_data->is_egress = !!key.is_egress;
   11788                 :          0 :         tbl_data->is_transfer = !!key.is_fdb;
   11789                 :          0 :         tbl_data->dummy = !!key.dummy;
   11790                 :          0 :         tbl_data->level = key.level;
   11791                 :          0 :         tbl_data->id = key.id;
   11792                 :            :         tbl = &tbl_data->tbl;
   11793         [ #  # ]:          0 :         if (key.dummy)
   11794                 :          0 :                 return &tbl_data->entry;
   11795         [ #  # ]:          0 :         if (key.is_fdb)
   11796                 :          0 :                 domain = sh->fdb_domain;
   11797         [ #  # ]:          0 :         else if (key.is_egress)
   11798                 :          0 :                 domain = sh->tx_domain;
   11799                 :            :         else
   11800                 :          0 :                 domain = sh->rx_domain;
   11801                 :            :         ret = mlx5_flow_os_create_flow_tbl(domain, key.level, &tbl->obj);
   11802                 :            :         if (ret) {
   11803                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11804                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11805                 :            :                                    NULL, "cannot create flow table object");
   11806                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11807                 :          0 :                 return NULL;
   11808                 :            :         }
   11809         [ #  # ]:          0 :         if (key.level != 0) {
   11810                 :            :                 ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
   11811                 :            :                                         (tbl->obj, &tbl_data->jump.action);
   11812                 :            :                 if (ret) {
   11813                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   11814                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11815                 :            :                                            NULL,
   11816                 :            :                                            "cannot create flow jump action");
   11817                 :          0 :                         mlx5_flow_os_destroy_flow_tbl(tbl->obj);
   11818                 :          0 :                         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11819                 :          0 :                         return NULL;
   11820                 :            :                 }
   11821                 :            :         }
   11822   [ #  #  #  # ]:          0 :         MKSTR(matcher_name, "%s_%s_%u_%u_matcher_list",
   11823                 :            :               key.is_fdb ? "FDB" : "NIC", key.is_egress ? "egress" : "ingress",
   11824                 :            :               key.level, key.id);
   11825                 :          0 :         tbl_data->matchers = mlx5_list_create(matcher_name, sh, true,
   11826                 :            :                                               mlx5_flow_matcher_create_cb,
   11827                 :            :                                               mlx5_flow_matcher_match_cb,
   11828                 :            :                                               mlx5_flow_matcher_remove_cb,
   11829                 :            :                                               mlx5_flow_matcher_clone_cb,
   11830                 :            :                                               mlx5_flow_matcher_clone_free_cb);
   11831         [ #  # ]:          0 :         if (!tbl_data->matchers) {
   11832                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11833                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11834                 :            :                                    NULL,
   11835                 :            :                                    "cannot create tbl matcher list");
   11836                 :          0 :                 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action);
   11837                 :          0 :                 mlx5_flow_os_destroy_flow_tbl(tbl->obj);
   11838                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx);
   11839                 :          0 :                 return NULL;
   11840                 :            :         }
   11841                 :          0 :         return &tbl_data->entry;
   11842                 :            : }
   11843                 :            : 
   11844                 :            : int
   11845                 :          0 : mlx5_flow_dv_tbl_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
   11846                 :            :                           void *cb_ctx)
   11847                 :            : {
   11848                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11849                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11850                 :            :                 container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11851                 :          0 :         union mlx5_flow_tbl_key key = { .v64 =  *(uint64_t *)(ctx->data) };
   11852                 :            : 
   11853                 :          0 :         return tbl_data->level != key.level ||
   11854         [ #  # ]:          0 :                tbl_data->id != key.id ||
   11855         [ #  # ]:          0 :                tbl_data->dummy != key.dummy ||
   11856   [ #  #  #  # ]:          0 :                tbl_data->is_transfer != !!key.is_fdb ||
   11857         [ #  # ]:          0 :                tbl_data->is_egress != !!key.is_egress;
   11858                 :            : }
   11859                 :            : 
   11860                 :            : struct mlx5_list_entry *
   11861                 :          0 : mlx5_flow_dv_tbl_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
   11862                 :            :                           void *cb_ctx)
   11863                 :            : {
   11864                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11865                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   11866                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11867                 :          0 :         struct rte_flow_error *error = ctx->error;
   11868                 :          0 :         uint32_t idx = 0;
   11869                 :            :         struct mlx5_flow_tbl_data_entry *old_resource;
   11870                 :            : 
   11871                 :          0 :         tbl_data = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_JUMP], &idx);
   11872         [ #  # ]:          0 :         if (!tbl_data) {
   11873                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11874                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   11875                 :            :                                    NULL,
   11876                 :            :                                    "cannot allocate flow table data entry");
   11877                 :          0 :                 return NULL;
   11878                 :            :         }
   11879                 :            :         old_resource = container_of(oentry, typeof(*old_resource), entry);
   11880                 :            :         memcpy(tbl_data, old_resource, sizeof(*tbl_data));
   11881                 :          0 :         tbl_data->idx = idx;
   11882                 :          0 :         return &tbl_data->entry;
   11883                 :            : }
   11884                 :            : 
   11885                 :            : void
   11886                 :          0 : mlx5_flow_dv_tbl_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11887                 :            : {
   11888                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11889                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11890                 :            :                     container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11891                 :            : 
   11892                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx);
   11893                 :          0 : }
   11894                 :            : 
   11895                 :            : /**
   11896                 :            :  * Get a flow table.
   11897                 :            :  *
   11898                 :            :  * @param[in, out] dev
   11899                 :            :  *   Pointer to rte_eth_dev structure.
   11900                 :            :  * @param[in] table_level
   11901                 :            :  *   Table level to use.
   11902                 :            :  * @param[in] egress
   11903                 :            :  *   Direction of the table.
   11904                 :            :  * @param[in] transfer
   11905                 :            :  *   E-Switch or NIC flow.
   11906                 :            :  * @param[in] dummy
   11907                 :            :  *   Dummy entry for dv API.
   11908                 :            :  * @param[in] table_id
   11909                 :            :  *   Table id to use.
   11910                 :            :  * @param[out] error
   11911                 :            :  *   pointer to error structure.
   11912                 :            :  *
   11913                 :            :  * @return
   11914                 :            :  *   Returns tables resource based on the index, NULL in case of failed.
   11915                 :            :  */
   11916                 :            : struct mlx5_flow_tbl_resource *
   11917                 :          0 : mlx5_flow_dv_tbl_resource_get(struct rte_eth_dev *dev,
   11918                 :            :                               uint32_t table_level, uint8_t egress,
   11919                 :            :                               uint8_t transfer,
   11920                 :            :                               bool external,
   11921                 :            :                               const struct mlx5_flow_tunnel *tunnel,
   11922                 :            :                               uint32_t group_id, uint8_t dummy,
   11923                 :            :                               uint32_t table_id,
   11924                 :            :                               struct rte_flow_error *error)
   11925                 :            : {
   11926                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   11927                 :          0 :         union mlx5_flow_tbl_key table_key = {
   11928                 :            :                 {
   11929                 :            :                         .level = table_level,
   11930                 :            :                         .id = table_id,
   11931                 :            :                         .reserved = 0,
   11932                 :          0 :                         .dummy = !!dummy,
   11933                 :          0 :                         .is_fdb = !!transfer,
   11934                 :          0 :                         .is_egress = !!egress,
   11935                 :            :                 }
   11936                 :            :         };
   11937                 :          0 :         struct mlx5_flow_tbl_tunnel_prm tt_prm = {
   11938                 :            :                 .tunnel = tunnel,
   11939                 :            :                 .group_id = group_id,
   11940                 :            :                 .external = external,
   11941                 :            :         };
   11942                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   11943                 :            :                 .dev = dev,
   11944                 :            :                 .error = error,
   11945                 :            :                 .data = &table_key.v64,
   11946                 :            :                 .data2 = &tt_prm,
   11947                 :            :         };
   11948                 :            :         struct mlx5_list_entry *entry;
   11949                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   11950                 :            : 
   11951                 :          0 :         entry = mlx5_hlist_register(priv->sh->flow_tbls, table_key.v64, &ctx);
   11952         [ #  # ]:          0 :         if (!entry) {
   11953                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   11954                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   11955                 :            :                                    "cannot get table");
   11956                 :          0 :                 return NULL;
   11957                 :            :         }
   11958         [ #  # ]:          0 :         DRV_LOG(DEBUG, "table_level %u table_id %u "
   11959                 :            :                 "tunnel %u group %u registered.",
   11960                 :            :                 table_level, table_id,
   11961                 :            :                 tunnel ? tunnel->tunnel_id : 0, group_id);
   11962                 :            :         tbl_data = container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11963                 :          0 :         return &tbl_data->tbl;
   11964                 :            : }
   11965                 :            : 
   11966                 :            : void
   11967                 :          0 : mlx5_flow_dv_tbl_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   11968                 :            : {
   11969                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   11970                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   11971                 :            :                     container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
   11972                 :            : 
   11973                 :            :         MLX5_ASSERT(entry && sh);
   11974         [ #  # ]:          0 :         if (tbl_data->jump.action)
   11975                 :            :                 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action);
   11976         [ #  # ]:          0 :         if (tbl_data->tbl.obj)
   11977                 :            :                 mlx5_flow_os_destroy_flow_tbl(tbl_data->tbl.obj);
   11978         [ #  # ]:          0 :         if (tbl_data->tunnel_offload && tbl_data->external) {
   11979                 :            :                 struct mlx5_list_entry *he;
   11980                 :            :                 struct mlx5_hlist *tunnel_grp_hash;
   11981                 :          0 :                 struct mlx5_flow_tunnel_hub *thub = sh->tunnel_hub;
   11982                 :          0 :                 union tunnel_tbl_key tunnel_key = {
   11983                 :          0 :                         .tunnel_id = tbl_data->tunnel ?
   11984         [ #  # ]:          0 :                                         tbl_data->tunnel->tunnel_id : 0,
   11985                 :          0 :                         .group = tbl_data->group_id
   11986                 :            :                 };
   11987                 :          0 :                 uint32_t table_level = tbl_data->level;
   11988                 :          0 :                 struct mlx5_flow_cb_ctx ctx = {
   11989                 :            :                         .data = (void *)&tunnel_key.val,
   11990                 :            :                 };
   11991                 :            : 
   11992                 :            :                 tunnel_grp_hash = tbl_data->tunnel ?
   11993         [ #  # ]:          0 :                                         tbl_data->tunnel->groups :
   11994                 :            :                                         thub->groups;
   11995                 :          0 :                 he = mlx5_hlist_lookup(tunnel_grp_hash, tunnel_key.val, &ctx);
   11996         [ #  # ]:          0 :                 if (he)
   11997                 :          0 :                         mlx5_hlist_unregister(tunnel_grp_hash, he);
   11998         [ #  # ]:          0 :                 DRV_LOG(DEBUG,
   11999                 :            :                         "table_level %u id %u tunnel %u group %u released.",
   12000                 :            :                         table_level,
   12001                 :            :                         tbl_data->id,
   12002                 :            :                         tbl_data->tunnel ?
   12003                 :            :                         tbl_data->tunnel->tunnel_id : 0,
   12004                 :            :                         tbl_data->group_id);
   12005                 :            :         }
   12006         [ #  # ]:          0 :         if (tbl_data->matchers)
   12007                 :          0 :                 mlx5_list_destroy(tbl_data->matchers);
   12008                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx);
   12009                 :          0 : }
   12010                 :            : 
   12011                 :            : /**
   12012                 :            :  * Release a flow table.
   12013                 :            :  *
   12014                 :            :  * @param[in] sh
   12015                 :            :  *   Pointer to device shared structure.
   12016                 :            :  * @param[in] tbl
   12017                 :            :  *   Table resource to be released.
   12018                 :            :  *
   12019                 :            :  * @return
   12020                 :            :  *   Returns 0 if table was released, else return 1;
   12021                 :            :  */
   12022                 :            : int
   12023                 :          0 : mlx5_flow_dv_tbl_resource_release(struct mlx5_dev_ctx_shared *sh,
   12024                 :            :                                   struct mlx5_flow_tbl_resource *tbl)
   12025                 :            : {
   12026                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data =
   12027                 :          0 :                 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
   12028                 :            : 
   12029         [ #  # ]:          0 :         if (!tbl)
   12030                 :            :                 return 0;
   12031                 :          0 :         return mlx5_hlist_unregister(sh->flow_tbls, &tbl_data->entry);
   12032                 :            : }
   12033                 :            : 
   12034                 :            : int
   12035                 :          0 : mlx5_flow_matcher_match_cb(void *tool_ctx __rte_unused,
   12036                 :            :                          struct mlx5_list_entry *entry, void *cb_ctx)
   12037                 :            : {
   12038                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12039                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   12040                 :            :         struct mlx5_flow_dv_matcher *cur = container_of(entry, typeof(*cur),
   12041                 :            :                                                         entry);
   12042                 :            : 
   12043                 :          0 :         return cur->crc != ref->crc ||
   12044         [ #  # ]:          0 :                cur->priority != ref->priority ||
   12045                 :          0 :                memcmp((const void *)cur->mask.buf,
   12046         [ #  # ]:          0 :                       (const void *)ref->mask.buf, ref->mask.size);
   12047                 :            : }
   12048                 :            : 
   12049                 :            : struct mlx5_list_entry *
   12050                 :          0 : mlx5_flow_matcher_create_cb(void *tool_ctx, void *cb_ctx)
   12051                 :            : {
   12052                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12053                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12054                 :          0 :         struct mlx5_flow_dv_matcher *ref = ctx->data;
   12055                 :            :         struct mlx5_flow_dv_matcher *resource;
   12056                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   12057                 :            :         const struct rte_flow_item *items;
   12058                 :            : #endif
   12059                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   12060                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   12061                 :          0 :                 .match_mask = (void *)&ref->mask,
   12062                 :            :         };
   12063                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   12064                 :            :         int ret;
   12065                 :            : 
   12066                 :          0 :         resource = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*resource), 0,
   12067                 :            :                                SOCKET_ID_ANY);
   12068         [ #  # ]:          0 :         if (!resource) {
   12069                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12070                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12071                 :            :                                    "cannot create matcher");
   12072                 :          0 :                 return NULL;
   12073                 :            :         }
   12074                 :          0 :         *resource = *ref;
   12075         [ #  # ]:          0 :         if (sh->config.dv_flow_en != 2) {
   12076                 :          0 :                 tbl = container_of(ref->tbl, typeof(*tbl), tbl);
   12077                 :          0 :                 dv_attr.match_criteria_enable =
   12078         [ #  # ]:          0 :                         flow_dv_matcher_enable(resource->mask.buf);
   12079                 :            :                 __flow_dv_adjust_buf_size(&ref->mask.size,
   12080                 :            :                                         dv_attr.match_criteria_enable);
   12081                 :          0 :                 dv_attr.priority = ref->priority;
   12082         [ #  # ]:          0 :                 if (tbl->is_egress)
   12083                 :          0 :                         dv_attr.flags |= IBV_FLOW_ATTR_FLAGS_EGRESS;
   12084                 :          0 :                 ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   12085                 :            :                                                 tbl->tbl.obj,
   12086                 :            :                                                 &resource->matcher_object);
   12087                 :            :                 if (ret) {
   12088                 :          0 :                         mlx5_free(resource);
   12089                 :          0 :                         rte_flow_error_set(ctx->error, ENOMEM,
   12090                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12091                 :            :                                         "cannot create matcher");
   12092                 :          0 :                         return NULL;
   12093                 :            :                 }
   12094                 :            :         } else {
   12095                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   12096                 :          0 :                 items = *((const struct rte_flow_item **)(ctx->data2));
   12097         [ #  # ]:          0 :                 if (!items)
   12098                 :          0 :                         goto error;
   12099                 :          0 :                 resource->matcher_object = mlx5dr_bwc_matcher_create
   12100                 :          0 :                                 (resource->group->tbl, resource->priority, items);
   12101         [ #  # ]:          0 :                 if (!resource->matcher_object)
   12102                 :          0 :                         goto error;
   12103                 :            : #else
   12104                 :            :                 goto error;
   12105                 :            : #endif
   12106                 :            :         }
   12107                 :          0 :         return &resource->entry;
   12108                 :          0 : error:
   12109                 :          0 :         mlx5_free(resource);
   12110                 :          0 :         return NULL;
   12111                 :            : }
   12112                 :            : 
   12113                 :            : /**
   12114                 :            :  * Register the flow matcher.
   12115                 :            :  *
   12116                 :            :  * @param[in, out] dev
   12117                 :            :  *   Pointer to rte_eth_dev structure.
   12118                 :            :  * @param[in, out] matcher
   12119                 :            :  *   Pointer to flow matcher.
   12120                 :            :  * @param[in, out] key
   12121                 :            :  *   Pointer to flow table key.
   12122                 :            :  * @parm[in, out] dev_flow
   12123                 :            :  *   Pointer to the dev_flow.
   12124                 :            :  * @param[out] error
   12125                 :            :  *   pointer to error structure.
   12126                 :            :  *
   12127                 :            :  * @return
   12128                 :            :  *   0 on success otherwise -errno and errno is set.
   12129                 :            :  */
   12130                 :            : static int
   12131                 :          0 : flow_dv_matcher_register(struct rte_eth_dev *dev,
   12132                 :            :                          struct mlx5_flow_dv_matcher *ref,
   12133                 :            :                          union mlx5_flow_tbl_key *key,
   12134                 :            :                          struct mlx5_flow *dev_flow,
   12135                 :            :                          const struct mlx5_flow_tunnel *tunnel,
   12136                 :            :                          uint32_t group_id,
   12137                 :            :                          struct rte_flow_error *error)
   12138                 :            : {
   12139                 :            :         struct mlx5_list_entry *entry;
   12140                 :            :         struct mlx5_flow_dv_matcher *resource;
   12141                 :            :         struct mlx5_flow_tbl_resource *tbl;
   12142                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   12143                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12144                 :            :                 .error = error,
   12145                 :            :                 .data = ref,
   12146                 :            :         };
   12147                 :            :         /**
   12148                 :            :          * tunnel offload API requires this registration for cases when
   12149                 :            :          * tunnel match rule was inserted before tunnel set rule.
   12150                 :            :          */
   12151                 :          0 :         tbl = mlx5_flow_dv_tbl_resource_get(dev, key->level,
   12152                 :          0 :                                             key->is_egress, key->is_fdb,
   12153                 :          0 :                                             dev_flow->external, tunnel,
   12154                 :          0 :                                             group_id, 0, key->id, error);
   12155         [ #  # ]:          0 :         if (!tbl)
   12156                 :          0 :                 return -rte_errno;      /* No need to refill the error info */
   12157                 :          0 :         tbl_data = container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
   12158                 :          0 :         ref->tbl = tbl;
   12159                 :          0 :         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   12160         [ #  # ]:          0 :         if (!entry) {
   12161                 :          0 :                 mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   12162                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   12163                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12164                 :            :                                           "cannot allocate ref memory");
   12165                 :            :         }
   12166                 :            :         resource = container_of(entry, typeof(*resource), entry);
   12167                 :          0 :         dev_flow->handle->dvh.matcher = resource;
   12168                 :          0 :         return 0;
   12169                 :            : }
   12170                 :            : 
   12171                 :            : struct mlx5_list_entry *
   12172                 :          0 : mlx5_flow_dv_tag_create_cb(void *tool_ctx, void *cb_ctx)
   12173                 :            : {
   12174                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12175                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12176                 :            :         struct mlx5_flow_dv_tag_resource *entry;
   12177                 :          0 :         uint32_t idx = 0;
   12178                 :            :         int ret;
   12179                 :            : 
   12180                 :          0 :         entry = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_TAG], &idx);
   12181         [ #  # ]:          0 :         if (!entry) {
   12182                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12183                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12184                 :            :                                    "cannot allocate resource memory");
   12185                 :          0 :                 return NULL;
   12186                 :            :         }
   12187                 :          0 :         entry->idx = idx;
   12188                 :          0 :         entry->tag_id = *(uint32_t *)(ctx->data);
   12189                 :            :         ret = mlx5_flow_os_create_flow_action_tag(entry->tag_id,
   12190                 :            :                                                   &entry->action);
   12191                 :            :         if (ret) {
   12192                 :          0 :                 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], idx);
   12193                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12194                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12195                 :            :                                    NULL, "cannot create action");
   12196                 :          0 :                 return NULL;
   12197                 :            :         }
   12198                 :          0 :         return &entry->entry;
   12199                 :            : }
   12200                 :            : 
   12201                 :            : int
   12202                 :          0 : mlx5_flow_dv_tag_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry,
   12203                 :            :                      void *cb_ctx)
   12204                 :            : {
   12205                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12206                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12207                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12208                 :            : 
   12209                 :          0 :         return *(uint32_t *)(ctx->data) != tag->tag_id;
   12210                 :            : }
   12211                 :            : 
   12212                 :            : struct mlx5_list_entry *
   12213                 :          0 : mlx5_flow_dv_tag_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
   12214                 :            :                      void *cb_ctx)
   12215                 :            : {
   12216                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12217                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12218                 :            :         struct mlx5_flow_dv_tag_resource *entry;
   12219                 :            :         struct mlx5_flow_dv_tag_resource *old_entry;
   12220                 :          0 :         uint32_t idx = 0;
   12221                 :            : 
   12222                 :          0 :         entry = mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_TAG], &idx);
   12223         [ #  # ]:          0 :         if (!entry) {
   12224                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12225                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   12226                 :            :                                    "cannot allocate tag resource memory");
   12227                 :          0 :                 return NULL;
   12228                 :            :         }
   12229                 :            :         old_entry = container_of(oentry, typeof(*old_entry), entry);
   12230                 :            :         memcpy(entry, old_entry, sizeof(*entry));
   12231                 :          0 :         entry->idx = idx;
   12232                 :          0 :         return &entry->entry;
   12233                 :            : }
   12234                 :            : 
   12235                 :            : void
   12236                 :          0 : mlx5_flow_dv_tag_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   12237                 :            : {
   12238                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12239                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12240                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12241                 :            : 
   12242                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx);
   12243                 :          0 : }
   12244                 :            : 
   12245                 :            : /**
   12246                 :            :  * Find existing tag resource or create and register a new one.
   12247                 :            :  *
   12248                 :            :  * @param dev[in, out]
   12249                 :            :  *   Pointer to rte_eth_dev structure.
   12250                 :            :  * @param[in, out] tag_be24
   12251                 :            :  *   Tag value in big endian then R-shift 8.
   12252                 :            :  * @parm[in, out] dev_flow
   12253                 :            :  *   Pointer to the dev_flow.
   12254                 :            :  * @param[out] error
   12255                 :            :  *   pointer to error structure.
   12256                 :            :  *
   12257                 :            :  * @return
   12258                 :            :  *   0 on success otherwise -errno and errno is set.
   12259                 :            :  */
   12260                 :            : static int
   12261                 :          0 : flow_dv_tag_resource_register
   12262                 :            :                         (struct rte_eth_dev *dev,
   12263                 :            :                          uint32_t tag_be24,
   12264                 :            :                          struct mlx5_flow *dev_flow,
   12265                 :            :                          struct rte_flow_error *error)
   12266                 :            : {
   12267                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12268                 :            :         struct mlx5_flow_dv_tag_resource *resource;
   12269                 :            :         struct mlx5_list_entry *entry;
   12270                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12271                 :            :                                         .error = error,
   12272                 :            :                                         .data = &tag_be24,
   12273                 :            :                                         };
   12274                 :            :         struct mlx5_hlist *tag_table;
   12275                 :            : 
   12276                 :          0 :         tag_table = flow_dv_hlist_prepare(priv->sh, &priv->sh->tag_table,
   12277                 :            :                                       "tags",
   12278                 :            :                                       MLX5_TAGS_HLIST_ARRAY_SIZE,
   12279                 :          0 :                                       false, false, priv->sh,
   12280                 :            :                                       mlx5_flow_dv_tag_create_cb,
   12281                 :            :                                       mlx5_flow_dv_tag_match_cb,
   12282                 :            :                                       mlx5_flow_dv_tag_remove_cb,
   12283                 :            :                                       mlx5_flow_dv_tag_clone_cb,
   12284                 :            :                                       mlx5_flow_dv_tag_clone_free_cb,
   12285                 :            :                                       error);
   12286         [ #  # ]:          0 :         if (unlikely(!tag_table))
   12287                 :          0 :                 return -rte_errno;
   12288                 :          0 :         entry = mlx5_hlist_register(tag_table, tag_be24, &ctx);
   12289         [ #  # ]:          0 :         if (entry) {
   12290                 :            :                 resource = container_of(entry, struct mlx5_flow_dv_tag_resource,
   12291                 :            :                                         entry);
   12292                 :          0 :                 dev_flow->handle->dvh.rix_tag = resource->idx;
   12293                 :          0 :                 dev_flow->dv.tag_resource = resource;
   12294                 :          0 :                 return 0;
   12295                 :            :         }
   12296                 :          0 :         return -rte_errno;
   12297                 :            : }
   12298                 :            : 
   12299                 :            : void
   12300                 :          0 : mlx5_flow_dv_tag_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   12301                 :            : {
   12302                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   12303                 :            :         struct mlx5_flow_dv_tag_resource *tag =
   12304                 :            :                    container_of(entry, struct mlx5_flow_dv_tag_resource, entry);
   12305                 :            : 
   12306                 :            :         MLX5_ASSERT(tag && sh && tag->action);
   12307                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(tag->action));
   12308                 :          0 :         DRV_LOG(DEBUG, "Tag %p: removed.", (void *)tag);
   12309                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx);
   12310                 :          0 : }
   12311                 :            : 
   12312                 :            : /**
   12313                 :            :  * Release the tag.
   12314                 :            :  *
   12315                 :            :  * @param dev
   12316                 :            :  *   Pointer to Ethernet device.
   12317                 :            :  * @param tag_idx
   12318                 :            :  *   Tag index.
   12319                 :            :  *
   12320                 :            :  * @return
   12321                 :            :  *   1 while a reference on it exists, 0 when freed.
   12322                 :            :  */
   12323                 :            : static int
   12324                 :          0 : flow_dv_tag_release(struct rte_eth_dev *dev,
   12325                 :            :                     uint32_t tag_idx)
   12326                 :            : {
   12327                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12328                 :            :         struct mlx5_flow_dv_tag_resource *tag;
   12329                 :            : 
   12330                 :          0 :         tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG], tag_idx);
   12331         [ #  # ]:          0 :         if (!tag)
   12332                 :            :                 return 0;
   12333                 :          0 :         DRV_LOG(DEBUG, "port %u tag %p: refcnt %d--",
   12334                 :            :                 dev->data->port_id, (void *)tag, tag->entry.ref_cnt);
   12335                 :          0 :         return mlx5_hlist_unregister(priv->sh->tag_table, &tag->entry);
   12336                 :            : }
   12337                 :            : 
   12338                 :            : /**
   12339                 :            :  * Translate action PORT_ID / REPRESENTED_PORT to vport.
   12340                 :            :  *
   12341                 :            :  * @param[in] dev
   12342                 :            :  *   Pointer to rte_eth_dev structure.
   12343                 :            :  * @param[in] action
   12344                 :            :  *   Pointer to action PORT_ID / REPRESENTED_PORT.
   12345                 :            :  * @param[out] dst_port_id
   12346                 :            :  *   The target port ID.
   12347                 :            :  * @param[out] error
   12348                 :            :  *   Pointer to the error structure.
   12349                 :            :  *
   12350                 :            :  * @return
   12351                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   12352                 :            :  */
   12353                 :            : static int
   12354                 :          0 : flow_dv_translate_action_port_id(struct rte_eth_dev *dev,
   12355                 :            :                                  const struct rte_flow_action *action,
   12356                 :            :                                  uint32_t *dst_port_id,
   12357                 :            :                                  struct rte_flow_error *error)
   12358                 :            : {
   12359                 :            :         uint32_t port;
   12360                 :            :         struct mlx5_priv *priv;
   12361                 :            : 
   12362      [ #  #  # ]:          0 :         switch (action->type) {
   12363                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID: {
   12364                 :            :                 const struct rte_flow_action_port_id *conf;
   12365                 :            : 
   12366                 :          0 :                 conf = (const struct rte_flow_action_port_id *)action->conf;
   12367         [ #  # ]:          0 :                 port = conf->original ? dev->data->port_id : conf->id;
   12368                 :            :                 break;
   12369                 :            :         }
   12370                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: {
   12371                 :            :                 const struct rte_flow_action_ethdev *ethdev;
   12372                 :            : 
   12373                 :          0 :                 ethdev = (const struct rte_flow_action_ethdev *)action->conf;
   12374                 :          0 :                 port = ethdev->port_id;
   12375                 :          0 :                 break;
   12376                 :            :         }
   12377                 :          0 :         default:
   12378                 :            :                 MLX5_ASSERT(false);
   12379                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   12380                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, action,
   12381                 :            :                                           "unknown E-Switch action");
   12382                 :            :         }
   12383                 :            : 
   12384                 :          0 :         priv = mlx5_port_to_eswitch_info(port, false);
   12385         [ #  # ]:          0 :         if (!priv)
   12386                 :          0 :                 return rte_flow_error_set(error, -rte_errno,
   12387                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   12388                 :            :                                           NULL,
   12389                 :            :                                           "No eswitch info was found for port");
   12390                 :            : #ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT
   12391                 :            :         /*
   12392                 :            :          * This parameter is transferred to
   12393                 :            :          * mlx5dv_dr_action_create_dest_ib_port().
   12394                 :            :          */
   12395                 :          0 :         *dst_port_id = priv->dev_port;
   12396                 :            : #else
   12397                 :            :         /*
   12398                 :            :          * Legacy mode, no LAG configurations is supported.
   12399                 :            :          * This parameter is transferred to
   12400                 :            :          * mlx5dv_dr_action_create_dest_vport().
   12401                 :            :          */
   12402                 :            :         *dst_port_id = priv->vport_id;
   12403                 :            : #endif
   12404                 :          0 :         return 0;
   12405                 :            : }
   12406                 :            : 
   12407                 :            : /**
   12408                 :            :  * Create a counter with aging configuration.
   12409                 :            :  *
   12410                 :            :  * @param[in] dev
   12411                 :            :  *   Pointer to rte_eth_dev structure.
   12412                 :            :  * @param[in] dev_flow
   12413                 :            :  *   Pointer to the mlx5_flow.
   12414                 :            :  * @param[out] count
   12415                 :            :  *   Pointer to the counter action configuration.
   12416                 :            :  * @param[in] age
   12417                 :            :  *   Pointer to the aging action configuration.
   12418                 :            :  *
   12419                 :            :  * @return
   12420                 :            :  *   Index to flow counter on success, 0 otherwise.
   12421                 :            :  */
   12422                 :            : static uint32_t
   12423                 :          0 : flow_dv_translate_create_counter(struct rte_eth_dev *dev,
   12424                 :            :                                 struct mlx5_flow *dev_flow,
   12425                 :            :                                 const struct rte_flow_action_count *count
   12426                 :            :                                         __rte_unused,
   12427                 :            :                                 const struct rte_flow_action_age *age)
   12428                 :            : {
   12429                 :            :         uint32_t counter;
   12430                 :            :         struct mlx5_age_param *age_param;
   12431                 :            : 
   12432                 :          0 :         counter = flow_dv_counter_alloc(dev, !!age);
   12433         [ #  # ]:          0 :         if (!counter || age == NULL)
   12434                 :            :                 return counter;
   12435                 :            :         age_param = flow_dv_counter_idx_get_age(dev, counter);
   12436         [ #  # ]:          0 :         age_param->context = age->context ? age->context :
   12437                 :          0 :                 (void *)(uintptr_t)(dev_flow->flow_idx);
   12438                 :          0 :         age_param->timeout = age->timeout;
   12439                 :          0 :         age_param->port_id = dev->data->port_id;
   12440                 :          0 :         rte_atomic_store_explicit(&age_param->sec_since_last_hit, 0, rte_memory_order_relaxed);
   12441                 :          0 :         rte_atomic_store_explicit(&age_param->state, AGE_CANDIDATE, rte_memory_order_relaxed);
   12442                 :          0 :         return counter;
   12443                 :            : }
   12444                 :            : 
   12445                 :            : /**
   12446                 :            :  * Add Tx queue matcher
   12447                 :            :  *
   12448                 :            :  * @param[in] dev
   12449                 :            :  *   Pointer to rte_eth_dev structure.
   12450                 :            :  * @param[in, out] key
   12451                 :            :  *   Flow matcher value.
   12452                 :            :  * @param[in] item
   12453                 :            :  *   Flow pattern to translate.
   12454                 :            :  * @param[in] key_type
   12455                 :            :  *   Set flow matcher mask or value.
   12456                 :            :  *
   12457                 :            :  * @return
   12458                 :            :  *   0 on success otherwise -errno and errno is set.
   12459                 :            :  */
   12460                 :            : static int
   12461                 :          0 : flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev, void *key,
   12462                 :            :                                 const struct rte_flow_item *item, uint32_t key_type)
   12463                 :            : {
   12464                 :            :         const struct rte_flow_item_tx_queue *queue_m;
   12465                 :            :         const struct rte_flow_item_tx_queue *queue_v;
   12466                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   12467                 :            :         uint32_t tx_queue;
   12468                 :            :         uint32_t sqn = 0;
   12469                 :            :         int ret;
   12470                 :            : 
   12471   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, queue_v, queue_m, &rte_flow_item_tx_queue_mask);
             #  #  #  # ]
   12472         [ #  # ]:          0 :         if (!queue_m || !queue_v)
   12473                 :            :                 return -EINVAL;
   12474         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_V) {
   12475                 :          0 :                 tx_queue = queue_v->tx_queue;
   12476         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_V)
   12477                 :          0 :                         tx_queue &= queue_m->tx_queue;
   12478         [ #  # ]:          0 :                 ret = flow_hw_get_sqn(dev, tx_queue, &sqn);
   12479         [ #  # ]:          0 :                 if (unlikely(ret))
   12480                 :          0 :                         return -ret;
   12481                 :            :         } else {
   12482                 :            :                 /* Due to tx_queue to sqn converting, only fully masked value support. */
   12483         [ #  # ]:          0 :                 if (queue_m->tx_queue != rte_flow_item_tx_queue_mask.tx_queue)
   12484                 :            :                         return -EINVAL;
   12485                 :            :                 sqn = UINT32_MAX;
   12486                 :            :         }
   12487         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_sqn, sqn);
   12488                 :          0 :         return 0;
   12489                 :            : }
   12490                 :            : 
   12491                 :            : /**
   12492                 :            :  * Add SQ matcher
   12493                 :            :  *
   12494                 :            :  * @param[in, out] matcher
   12495                 :            :  *   Flow matcher.
   12496                 :            :  * @param[in, out] key
   12497                 :            :  *   Flow matcher value.
   12498                 :            :  * @param[in] item
   12499                 :            :  *   Flow pattern to translate.
   12500                 :            :  * @param[in] key_type
   12501                 :            :  *   Set flow matcher mask or value.
   12502                 :            :  */
   12503                 :            : static void
   12504                 :          0 : flow_dv_translate_item_sq(void *key,
   12505                 :            :                           const struct rte_flow_item *item,
   12506                 :            :                           uint32_t key_type)
   12507                 :            : {
   12508                 :            :         const struct mlx5_rte_flow_item_sq *queue_m;
   12509                 :            :         const struct mlx5_rte_flow_item_sq *queue_v;
   12510                 :          0 :         const struct mlx5_rte_flow_item_sq queue_mask = {
   12511                 :            :                 .queue = UINT32_MAX,
   12512                 :            :         };
   12513                 :            :         void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
   12514                 :            :         uint32_t queue;
   12515                 :            : 
   12516   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(item, key_type, queue_v, queue_m, &queue_mask);
             #  #  #  # ]
   12517         [ #  # ]:          0 :         if (!queue_m || !queue_v)
   12518                 :          0 :                 return;
   12519         [ #  # ]:          0 :         if (key_type & MLX5_SET_MATCHER_V) {
   12520                 :          0 :                 queue = queue_v->queue;
   12521         [ #  # ]:          0 :                 if (key_type == MLX5_SET_MATCHER_SW_V)
   12522                 :          0 :                         queue &= queue_m->queue;
   12523                 :            :         } else {
   12524                 :          0 :                 queue = queue_m->queue;
   12525                 :            :         }
   12526         [ #  # ]:          0 :         MLX5_SET(fte_match_set_misc, misc_v, source_sqn, queue);
   12527                 :            : }
   12528                 :            : 
   12529                 :            : /**
   12530                 :            :  * Set the hash fields according to the @p flow information.
   12531                 :            :  *
   12532                 :            :  * @param[in] item_flags
   12533                 :            :  *   The match pattern item flags.
   12534                 :            :  * @param[in] rss_desc
   12535                 :            :  *   Pointer to the mlx5_flow_rss_desc.
   12536                 :            :  * @param[out] hash_fields
   12537                 :            :  *   Pointer to the RSS hash fields.
   12538                 :            :  */
   12539                 :            : void
   12540                 :          0 : mlx5_flow_dv_hashfields_set(uint64_t item_flags,
   12541                 :            :                             struct mlx5_flow_rss_desc *rss_desc,
   12542                 :            :                             uint64_t *hash_fields)
   12543                 :            : {
   12544                 :            :         uint64_t items = item_flags;
   12545                 :            :         uint64_t fields = 0;
   12546                 :            :         int rss_inner = 0;
   12547         [ #  # ]:          0 :         uint64_t rss_types = rte_eth_rss_hf_refine(rss_desc->types);
   12548                 :            : 
   12549                 :            :         *hash_fields = 0;
   12550                 :            : #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
   12551         [ #  # ]:          0 :         if (rss_desc->level >= 2)
   12552                 :            :                 rss_inner = 1;
   12553                 :            : #endif
   12554   [ #  #  #  # ]:          0 :         if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV4)) ||
   12555         [ #  # ]:          0 :             (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV4))) {
   12556         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV4_LAYER_TYPES) {
   12557         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   12558                 :            :                                 fields |= IBV_RX_HASH_SRC_IPV4;
   12559         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   12560                 :            :                                 fields |= IBV_RX_HASH_DST_IPV4;
   12561                 :            :                         else
   12562                 :            :                                 fields |= MLX5_IPV4_IBV_RX_HASH;
   12563                 :            :                 }
   12564   [ #  #  #  #  :          0 :         } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV6)) ||
                   #  # ]
   12565         [ #  # ]:          0 :                    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV6))) {
   12566         [ #  # ]:          0 :                 if (rss_types & MLX5_IPV6_LAYER_TYPES) {
   12567         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   12568                 :            :                                 fields |= IBV_RX_HASH_SRC_IPV6;
   12569         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   12570                 :            :                                 fields |= IBV_RX_HASH_DST_IPV6;
   12571                 :            :                         else
   12572                 :            :                                 fields |= MLX5_IPV6_IBV_RX_HASH;
   12573                 :            :                 }
   12574                 :            :         }
   12575         [ #  # ]:          0 :         if (items & MLX5_FLOW_ITEM_ESP) {
   12576         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_ESP)
   12577                 :          0 :                         fields |= IBV_RX_HASH_IPSEC_SPI;
   12578                 :            :         }
   12579         [ #  # ]:          0 :         if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
   12580                 :          0 :                 *hash_fields = fields;
   12581                 :            :                 /*
   12582                 :            :                  * There is no match between the RSS types and the
   12583                 :            :                  * L3 protocol (IPv4/IPv6) defined in the flow rule.
   12584                 :            :                  */
   12585                 :          0 :                 return;
   12586                 :            :         }
   12587   [ #  #  #  #  :          0 :         if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
                   #  # ]
   12588         [ #  # ]:          0 :             (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP))) {
   12589         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_UDP) {
   12590         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   12591                 :          0 :                                 fields |= IBV_RX_HASH_SRC_PORT_UDP;
   12592         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   12593                 :          0 :                                 fields |= IBV_RX_HASH_DST_PORT_UDP;
   12594                 :            :                         else
   12595                 :          0 :                                 fields |= MLX5_UDP_IBV_RX_HASH;
   12596                 :            :                 }
   12597   [ #  #  #  #  :          0 :         } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_TCP)) ||
                   #  # ]
   12598         [ #  # ]:          0 :                    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_TCP))) {
   12599         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_TCP) {
   12600         [ #  # ]:          0 :                         if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   12601                 :          0 :                                 fields |= IBV_RX_HASH_SRC_PORT_TCP;
   12602         [ #  # ]:          0 :                         else if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   12603                 :          0 :                                 fields |= IBV_RX_HASH_DST_PORT_TCP;
   12604                 :            :                         else
   12605                 :          0 :                                 fields |= MLX5_TCP_IBV_RX_HASH;
   12606                 :            :                 }
   12607                 :            :         }
   12608         [ #  # ]:          0 :         if (rss_inner)
   12609                 :          0 :                 fields |= IBV_RX_HASH_INNER;
   12610                 :          0 :         *hash_fields = fields;
   12611                 :            : }
   12612                 :            : 
   12613                 :            : /**
   12614                 :            :  * Prepare an Rx Hash queue.
   12615                 :            :  *
   12616                 :            :  * @param dev
   12617                 :            :  *   Pointer to Ethernet device.
   12618                 :            :  * @param[in] dev_flow
   12619                 :            :  *   Pointer to the mlx5_flow.
   12620                 :            :  * @param[in] rss_desc
   12621                 :            :  *   Pointer to the mlx5_flow_rss_desc.
   12622                 :            :  * @param[out] hrxq_idx
   12623                 :            :  *   Hash Rx queue index.
   12624                 :            :  *
   12625                 :            :  * @return
   12626                 :            :  *   The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.
   12627                 :            :  */
   12628                 :            : static struct mlx5_hrxq *
   12629                 :          0 : flow_dv_hrxq_prepare(struct rte_eth_dev *dev,
   12630                 :            :                      struct mlx5_flow *dev_flow,
   12631                 :            :                      struct mlx5_flow_rss_desc *rss_desc,
   12632                 :            :                      uint32_t *hrxq_idx)
   12633                 :            : {
   12634                 :          0 :         struct mlx5_flow_handle *dh = dev_flow->handle;
   12635                 :          0 :         uint32_t shared_rss = rss_desc->shared_rss;
   12636                 :            :         struct mlx5_hrxq *hrxq;
   12637                 :            : 
   12638                 :            :         MLX5_ASSERT(rss_desc->queue_num);
   12639                 :          0 :         rss_desc->symmetric_hash_function = dev_flow->symmetric_hash_function;
   12640                 :          0 :         rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN;
   12641                 :          0 :         rss_desc->hash_fields = dev_flow->hash_fields;
   12642                 :          0 :         rss_desc->tunnel = !!(dh->layers & MLX5_FLOW_LAYER_TUNNEL);
   12643                 :          0 :         rss_desc->shared_rss = 0;
   12644         [ #  # ]:          0 :         if (rss_desc->hash_fields == 0)
   12645                 :          0 :                 rss_desc->queue_num = 1;
   12646                 :          0 :         hrxq = mlx5_hrxq_get(dev, rss_desc);
   12647         [ #  # ]:          0 :         *hrxq_idx = hrxq ? hrxq->idx : 0;
   12648                 :          0 :         rss_desc->shared_rss = shared_rss;
   12649                 :          0 :         return hrxq;
   12650                 :            : }
   12651                 :            : 
   12652                 :            : /**
   12653                 :            :  * Release sample sub action resource.
   12654                 :            :  *
   12655                 :            :  * @param[in, out] dev
   12656                 :            :  *   Pointer to rte_eth_dev structure.
   12657                 :            :  * @param[in] act_res
   12658                 :            :  *   Pointer to sample sub action resource.
   12659                 :            :  */
   12660                 :            : static void
   12661                 :          0 : flow_dv_sample_sub_actions_release(struct rte_eth_dev *dev,
   12662                 :            :                                    struct mlx5_flow_sub_actions_idx *act_res)
   12663                 :            : {
   12664         [ #  # ]:          0 :         if (act_res->rix_hrxq) {
   12665                 :          0 :                 mlx5_hrxq_release(dev, act_res->rix_hrxq);
   12666                 :          0 :                 act_res->rix_hrxq = 0;
   12667                 :            :         }
   12668         [ #  # ]:          0 :         if (act_res->rix_encap_decap) {
   12669                 :          0 :                 mlx5_flow_encap_decap_resource_release(dev, act_res->rix_encap_decap);
   12670                 :          0 :                 act_res->rix_encap_decap = 0;
   12671                 :            :         }
   12672         [ #  # ]:          0 :         if (act_res->rix_port_id_action) {
   12673                 :          0 :                 flow_dv_port_id_action_resource_release(dev,
   12674                 :            :                                                 act_res->rix_port_id_action);
   12675                 :          0 :                 act_res->rix_port_id_action = 0;
   12676                 :            :         }
   12677         [ #  # ]:          0 :         if (act_res->rix_tag) {
   12678                 :          0 :                 flow_dv_tag_release(dev, act_res->rix_tag);
   12679                 :          0 :                 act_res->rix_tag = 0;
   12680                 :            :         }
   12681         [ #  # ]:          0 :         if (act_res->rix_jump) {
   12682                 :          0 :                 flow_dv_jump_tbl_resource_release(dev, act_res->rix_jump);
   12683                 :          0 :                 act_res->rix_jump = 0;
   12684                 :            :         }
   12685                 :          0 : }
   12686                 :            : 
   12687                 :            : int
   12688                 :          0 : mlx5_flow_dv_sample_match_cb(void *tool_ctx __rte_unused,
   12689                 :            :                              struct mlx5_list_entry *entry, void *cb_ctx)
   12690                 :            : {
   12691                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12692                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12693                 :          0 :         struct mlx5_flow_dv_sample_resource *ctx_resource = ctx->data;
   12694                 :            :         struct mlx5_flow_dv_sample_resource *resource = container_of(entry,
   12695                 :            :                                                               typeof(*resource),
   12696                 :            :                                                               entry);
   12697                 :            : 
   12698         [ #  # ]:          0 :         if (ctx_resource->ratio == resource->ratio &&
   12699         [ #  # ]:          0 :             ctx_resource->ft_type == resource->ft_type &&
   12700         [ #  # ]:          0 :             ctx_resource->ft_id == resource->ft_id &&
   12701         [ #  # ]:          0 :             ctx_resource->set_action == resource->set_action &&
   12702                 :          0 :             !memcmp((void *)&ctx_resource->sample_act,
   12703         [ #  # ]:          0 :                     (void *)&resource->sample_act,
   12704                 :            :                     sizeof(struct mlx5_flow_sub_actions_list))) {
   12705                 :            :                 /*
   12706                 :            :                  * Existing sample action should release the prepared
   12707                 :            :                  * sub-actions reference counter.
   12708                 :            :                  */
   12709                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12710                 :            :                                                    &ctx_resource->sample_idx);
   12711                 :          0 :                 return 0;
   12712                 :            :         }
   12713                 :            :         return 1;
   12714                 :            : }
   12715                 :            : 
   12716                 :            : struct mlx5_list_entry *
   12717                 :          0 : mlx5_flow_dv_sample_create_cb(void *tool_ctx __rte_unused, void *cb_ctx)
   12718                 :            : {
   12719                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12720                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12721                 :          0 :         struct mlx5_flow_dv_sample_resource *ctx_resource = ctx->data;
   12722                 :          0 :         void **sample_dv_actions = ctx_resource->sub_actions;
   12723                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12724                 :            :         struct mlx5dv_dr_flow_sampler_attr sampler_attr;
   12725                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12726                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12727                 :            :         struct mlx5_flow_tbl_resource *tbl;
   12728                 :          0 :         uint32_t idx = 0;
   12729                 :            :         const uint32_t next_ft_step = 1;
   12730                 :          0 :         uint32_t next_ft_id = ctx_resource->ft_id + next_ft_step;
   12731                 :            :         uint8_t is_egress = 0;
   12732                 :            :         uint8_t is_transfer = 0;
   12733                 :          0 :         struct rte_flow_error *error = ctx->error;
   12734                 :            : 
   12735                 :            :         /* Register new sample resource. */
   12736                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);
   12737         [ #  # ]:          0 :         if (!resource) {
   12738                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12739                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12740                 :            :                                           NULL,
   12741                 :            :                                           "cannot allocate resource memory");
   12742                 :          0 :                 return NULL;
   12743                 :            :         }
   12744                 :          0 :         *resource = *ctx_resource;
   12745                 :            :         /* Create normal path table level */
   12746         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
   12747                 :            :                 is_transfer = 1;
   12748         [ #  # ]:          0 :         else if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX)
   12749                 :            :                 is_egress = 1;
   12750                 :          0 :         tbl = mlx5_flow_dv_tbl_resource_get(dev, next_ft_id,
   12751                 :            :                                             is_egress, is_transfer,
   12752                 :            :                                             true, NULL, 0, 0, 0, error);
   12753         [ #  # ]:          0 :         if (!tbl) {
   12754                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12755                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12756                 :            :                                           NULL,
   12757                 :            :                                           "fail to create normal path table "
   12758                 :            :                                           "for sample");
   12759                 :          0 :                 goto error;
   12760                 :            :         }
   12761                 :          0 :         resource->normal_path_tbl = tbl;
   12762         [ #  # ]:          0 :         if (ctx_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
   12763         [ #  # ]:          0 :                 if (!sh->default_miss_action) {
   12764                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   12765                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12766                 :            :                                                 NULL,
   12767                 :            :                                                 "default miss action was not "
   12768                 :            :                                                 "created");
   12769                 :          0 :                         goto error;
   12770                 :            :                 }
   12771                 :          0 :                 sample_dv_actions[ctx_resource->sample_act.actions_num++] =
   12772                 :            :                                                 sh->default_miss_action;
   12773                 :            :         }
   12774                 :            :         /* Create a DR sample action */
   12775                 :          0 :         sampler_attr.sample_ratio = resource->ratio;
   12776                 :          0 :         sampler_attr.default_next_table = tbl->obj;
   12777                 :          0 :         sampler_attr.num_sample_actions = ctx_resource->sample_act.actions_num;
   12778                 :          0 :         sampler_attr.sample_actions = (struct mlx5dv_dr_action **)
   12779                 :            :                                                         &sample_dv_actions[0];
   12780                 :          0 :         sampler_attr.action = resource->set_action;
   12781                 :            :         if (mlx5_os_flow_dr_create_flow_action_sampler
   12782                 :            :                         (&sampler_attr, &resource->verbs_action)) {
   12783                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12784                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12785                 :            :                                         NULL, "cannot create sample action");
   12786                 :          0 :                 goto error;
   12787                 :            :         }
   12788                 :          0 :         resource->idx = idx;
   12789                 :          0 :         resource->dev = dev;
   12790                 :          0 :         return &resource->entry;
   12791                 :          0 : error:
   12792         [ #  # ]:          0 :         if (resource->ft_type != MLX5DV_FLOW_TABLE_TYPE_FDB)
   12793                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   12794                 :            :                                                    &resource->sample_idx);
   12795         [ #  # ]:          0 :         if (resource->normal_path_tbl)
   12796                 :          0 :                 mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), resource->normal_path_tbl);
   12797                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE], idx);
   12798                 :          0 :         return NULL;
   12799                 :            : 
   12800                 :            : }
   12801                 :            : 
   12802                 :            : struct mlx5_list_entry *
   12803                 :          0 : mlx5_flow_dv_sample_clone_cb(void *tool_ctx __rte_unused,
   12804                 :            :                              struct mlx5_list_entry *entry __rte_unused,
   12805                 :            :                              void *cb_ctx)
   12806                 :            : {
   12807                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12808                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12809                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12810                 :            :         struct mlx5_flow_dv_sample_resource *old_resource;
   12811                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12812                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12813                 :          0 :         uint32_t idx = 0;
   12814                 :            : 
   12815                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx);
   12816         [ #  # ]:          0 :         if (!resource) {
   12817                 :          0 :                 rte_flow_error_set(ctx->error, ENOMEM,
   12818                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12819                 :            :                                    NULL,
   12820                 :            :                                    "cannot allocate resource memory");
   12821                 :          0 :                 return NULL;
   12822                 :            :         }
   12823                 :            :         old_resource = container_of(entry, typeof(*old_resource), entry);
   12824                 :            :         memcpy(resource, old_resource, sizeof(*resource));
   12825                 :          0 :         resource->idx = idx;
   12826                 :          0 :         resource->dev = dev;
   12827                 :          0 :         return &resource->entry;
   12828                 :            : }
   12829                 :            : 
   12830                 :            : void
   12831                 :          0 : mlx5_flow_dv_sample_clone_free_cb(void *tool_ctx __rte_unused,
   12832                 :            :                                   struct mlx5_list_entry *entry)
   12833                 :            : {
   12834                 :            :         struct mlx5_flow_dv_sample_resource *resource =
   12835                 :            :                                   container_of(entry, typeof(*resource), entry);
   12836                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   12837                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12838                 :            : 
   12839                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], resource->idx);
   12840                 :          0 : }
   12841                 :            : 
   12842                 :            : /**
   12843                 :            :  * Find existing sample resource or create and register a new one.
   12844                 :            :  *
   12845                 :            :  * @param[in, out] dev
   12846                 :            :  *   Pointer to rte_eth_dev structure.
   12847                 :            :  * @param[in] ref
   12848                 :            :  *   Pointer to sample resource reference.
   12849                 :            :  * @parm[in, out] dev_flow
   12850                 :            :  *   Pointer to the dev_flow.
   12851                 :            :  * @param[out] error
   12852                 :            :  *   pointer to error structure.
   12853                 :            :  *
   12854                 :            :  * @return
   12855                 :            :  *   0 on success otherwise -errno and errno is set.
   12856                 :            :  */
   12857                 :            : static int
   12858                 :          0 : flow_dv_sample_resource_register(struct rte_eth_dev *dev,
   12859                 :            :                          struct mlx5_flow_dv_sample_resource *ref,
   12860                 :            :                          struct mlx5_flow *dev_flow,
   12861                 :            :                          struct rte_flow_error *error)
   12862                 :            : {
   12863                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   12864                 :            :         struct mlx5_list_entry *entry;
   12865                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12866                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   12867                 :            :                 .dev = dev,
   12868                 :            :                 .error = error,
   12869                 :            :                 .data = ref,
   12870                 :            :         };
   12871                 :            : 
   12872                 :          0 :         entry = mlx5_list_register(priv->sh->sample_action_list, &ctx);
   12873         [ #  # ]:          0 :         if (!entry)
   12874                 :          0 :                 return -rte_errno;
   12875                 :            :         resource = container_of(entry, typeof(*resource), entry);
   12876                 :          0 :         dev_flow->handle->dvh.rix_sample = resource->idx;
   12877                 :          0 :         dev_flow->dv.sample_res = resource;
   12878                 :          0 :         return 0;
   12879                 :            : }
   12880                 :            : 
   12881                 :            : int
   12882                 :          0 : mlx5_flow_dv_dest_array_match_cb(void *tool_ctx __rte_unused,
   12883                 :            :                                  struct mlx5_list_entry *entry, void *cb_ctx)
   12884                 :            : {
   12885                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12886                 :          0 :         struct mlx5_flow_dv_dest_array_resource *ctx_resource = ctx->data;
   12887                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12888                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   12889                 :            :                                   container_of(entry, typeof(*resource), entry);
   12890                 :            :         uint32_t idx = 0;
   12891                 :            : 
   12892         [ #  # ]:          0 :         if (ctx_resource->num_of_dest == resource->num_of_dest &&
   12893                 :          0 :             ctx_resource->ft_type == resource->ft_type &&
   12894                 :          0 :             !memcmp((void *)resource->sample_act,
   12895                 :          0 :                     (void *)ctx_resource->sample_act,
   12896         [ #  # ]:          0 :                    (ctx_resource->num_of_dest *
   12897                 :            :                    sizeof(struct mlx5_flow_sub_actions_list)))) {
   12898                 :            :                 /*
   12899                 :            :                  * Existing sample action should release the prepared
   12900                 :            :                  * sub-actions reference counter.
   12901                 :            :                  */
   12902         [ #  # ]:          0 :                 for (idx = 0; idx < ctx_resource->num_of_dest; idx++)
   12903                 :          0 :                         flow_dv_sample_sub_actions_release(dev,
   12904                 :            :                                         &ctx_resource->sample_idx[idx]);
   12905                 :            :                 return 0;
   12906                 :            :         }
   12907                 :            :         return 1;
   12908                 :            : }
   12909                 :            : 
   12910                 :            : struct mlx5_list_entry *
   12911                 :          0 : mlx5_flow_dv_dest_array_create_cb(void *tool_ctx __rte_unused, void *cb_ctx)
   12912                 :            : {
   12913                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   12914                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   12915                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   12916                 :          0 :         struct mlx5_flow_dv_dest_array_resource *ctx_resource = ctx->data;
   12917                 :          0 :         struct mlx5dv_dr_action_dest_attr *dest_attr[MLX5_MAX_DEST_NUM] = { 0 };
   12918                 :            :         struct mlx5dv_dr_action_dest_reformat dest_reformat[MLX5_MAX_DEST_NUM];
   12919                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   12920                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   12921                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   12922                 :            :         struct mlx5dv_dr_domain *domain;
   12923                 :          0 :         uint32_t idx = 0, res_idx = 0;
   12924                 :          0 :         struct rte_flow_error *error = ctx->error;
   12925                 :            :         uint64_t action_flags;
   12926                 :            :         int ret;
   12927                 :            : 
   12928                 :            :         /* Register new destination array resource. */
   12929                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   12930                 :            :                                             &res_idx);
   12931         [ #  # ]:          0 :         if (!resource) {
   12932                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12933                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12934                 :            :                                           NULL,
   12935                 :            :                                           "cannot allocate resource memory");
   12936                 :          0 :                 return NULL;
   12937                 :            :         }
   12938                 :          0 :         *resource = *ctx_resource;
   12939         [ #  # ]:          0 :         if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB)
   12940                 :          0 :                 domain = sh->fdb_domain;
   12941         [ #  # ]:          0 :         else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX)
   12942                 :          0 :                 domain = sh->rx_domain;
   12943                 :            :         else
   12944                 :          0 :                 domain = sh->tx_domain;
   12945         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++) {
   12946                 :          0 :                 dest_attr[idx] = (struct mlx5dv_dr_action_dest_attr *)
   12947                 :          0 :                                  mlx5_malloc(MLX5_MEM_ZERO,
   12948                 :            :                                  sizeof(struct mlx5dv_dr_action_dest_attr),
   12949                 :            :                                  0, SOCKET_ID_ANY);
   12950         [ #  # ]:          0 :                 if (!dest_attr[idx]) {
   12951                 :          0 :                         rte_flow_error_set(error, ENOMEM,
   12952                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12953                 :            :                                            NULL,
   12954                 :            :                                            "cannot allocate resource memory");
   12955                 :          0 :                         goto error;
   12956                 :            :                 }
   12957                 :          0 :                 dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST;
   12958                 :            :                 sample_act = &ctx_resource->sample_act[idx];
   12959                 :          0 :                 action_flags = sample_act->action_flags;
   12960   [ #  #  #  #  :          0 :                 switch (action_flags) {
                      # ]
   12961                 :          0 :                 case MLX5_FLOW_ACTION_QUEUE:
   12962                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_queue_action;
   12963                 :          0 :                         break;
   12964                 :          0 :                 case (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP):
   12965                 :          0 :                         dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT;
   12966                 :          0 :                         dest_attr[idx]->dest_reformat = &dest_reformat[idx];
   12967                 :          0 :                         dest_attr[idx]->dest_reformat->reformat =
   12968                 :          0 :                                         sample_act->dr_encap_action;
   12969                 :          0 :                         dest_attr[idx]->dest_reformat->dest =
   12970                 :          0 :                                         sample_act->dr_port_id_action;
   12971                 :          0 :                         break;
   12972                 :          0 :                 case MLX5_FLOW_ACTION_PORT_ID:
   12973                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_port_id_action;
   12974                 :          0 :                         break;
   12975                 :          0 :                 case MLX5_FLOW_ACTION_JUMP:
   12976                 :          0 :                         dest_attr[idx]->dest = sample_act->dr_jump_action;
   12977                 :          0 :                         break;
   12978                 :          0 :                 default:
   12979                 :          0 :                         rte_flow_error_set(error, EINVAL,
   12980                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   12981                 :            :                                            NULL,
   12982                 :            :                                            "unsupported actions type");
   12983                 :          0 :                         goto error;
   12984                 :            :                 }
   12985                 :            :         }
   12986                 :            :         /* create a dest array action */
   12987                 :          0 :         ret = mlx5_os_flow_dr_create_flow_action_dest_array
   12988                 :            :                                                 (domain,
   12989                 :          0 :                                                  resource->num_of_dest,
   12990                 :            :                                                  dest_attr,
   12991                 :            :                                                  &resource->action);
   12992                 :            :         if (ret) {
   12993                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   12994                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   12995                 :            :                                    NULL,
   12996                 :            :                                    "cannot create destination array action");
   12997                 :          0 :                 goto error;
   12998                 :            :         }
   12999                 :          0 :         resource->idx = res_idx;
   13000                 :          0 :         resource->dev = dev;
   13001         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++)
   13002                 :          0 :                 mlx5_free(dest_attr[idx]);
   13003                 :          0 :         return &resource->entry;
   13004                 :            : error:
   13005         [ #  # ]:          0 :         for (idx = 0; idx < ctx_resource->num_of_dest; idx++) {
   13006                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   13007                 :            :                                                    &resource->sample_idx[idx]);
   13008         [ #  # ]:          0 :                 if (dest_attr[idx])
   13009                 :          0 :                         mlx5_free(dest_attr[idx]);
   13010                 :            :         }
   13011                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY], res_idx);
   13012                 :          0 :         return NULL;
   13013                 :            : }
   13014                 :            : 
   13015                 :            : struct mlx5_list_entry *
   13016                 :          0 : mlx5_flow_dv_dest_array_clone_cb(void *tool_ctx __rte_unused,
   13017                 :            :                                  struct mlx5_list_entry *entry __rte_unused,
   13018                 :            :                                  void *cb_ctx)
   13019                 :            : {
   13020                 :            :         struct mlx5_flow_cb_ctx *ctx = cb_ctx;
   13021                 :          0 :         struct rte_eth_dev *dev = ctx->dev;
   13022                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   13023                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13024                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   13025                 :          0 :         uint32_t res_idx = 0;
   13026                 :          0 :         struct rte_flow_error *error = ctx->error;
   13027                 :            : 
   13028                 :          0 :         resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   13029                 :            :                                       &res_idx);
   13030         [ #  # ]:          0 :         if (!resource) {
   13031                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   13032                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13033                 :            :                                           NULL,
   13034                 :            :                                           "cannot allocate dest-array memory");
   13035                 :          0 :                 return NULL;
   13036                 :            :         }
   13037                 :            :         memcpy(resource, entry, sizeof(*resource));
   13038                 :          0 :         resource->idx = res_idx;
   13039                 :          0 :         resource->dev = dev;
   13040                 :          0 :         return &resource->entry;
   13041                 :            : }
   13042                 :            : 
   13043                 :            : void
   13044                 :          0 : mlx5_flow_dv_dest_array_clone_free_cb(void *tool_ctx __rte_unused,
   13045                 :            :                                       struct mlx5_list_entry *entry)
   13046                 :            : {
   13047                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   13048                 :            :                         container_of(entry, typeof(*resource), entry);
   13049                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   13050                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13051                 :            : 
   13052                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], resource->idx);
   13053                 :          0 : }
   13054                 :            : 
   13055                 :            : /**
   13056                 :            :  * Find existing destination array resource or create and register a new one.
   13057                 :            :  *
   13058                 :            :  * @param[in, out] dev
   13059                 :            :  *   Pointer to rte_eth_dev structure.
   13060                 :            :  * @param[in] ref
   13061                 :            :  *   Pointer to destination array resource reference.
   13062                 :            :  * @parm[in, out] dev_flow
   13063                 :            :  *   Pointer to the dev_flow.
   13064                 :            :  * @param[out] error
   13065                 :            :  *   pointer to error structure.
   13066                 :            :  *
   13067                 :            :  * @return
   13068                 :            :  *   0 on success otherwise -errno and errno is set.
   13069                 :            :  */
   13070                 :            : static int
   13071                 :          0 : flow_dv_dest_array_resource_register(struct rte_eth_dev *dev,
   13072                 :            :                          struct mlx5_flow_dv_dest_array_resource *ref,
   13073                 :            :                          struct mlx5_flow *dev_flow,
   13074                 :            :                          struct rte_flow_error *error)
   13075                 :            : {
   13076                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   13077                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13078                 :            :         struct mlx5_list_entry *entry;
   13079                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   13080                 :            :                 .dev = dev,
   13081                 :            :                 .error = error,
   13082                 :            :                 .data = ref,
   13083                 :            :         };
   13084                 :            : 
   13085                 :          0 :         entry = mlx5_list_register(priv->sh->dest_array_list, &ctx);
   13086         [ #  # ]:          0 :         if (!entry)
   13087                 :          0 :                 return -rte_errno;
   13088                 :            :         resource = container_of(entry, typeof(*resource), entry);
   13089                 :          0 :         dev_flow->handle->dvh.rix_dest_array = resource->idx;
   13090                 :          0 :         dev_flow->dv.dest_array_res = resource;
   13091                 :          0 :         return 0;
   13092                 :            : }
   13093                 :            : 
   13094                 :            : /**
   13095                 :            :  * Convert Sample action to DV specification.
   13096                 :            :  *
   13097                 :            :  * @param[in] dev
   13098                 :            :  *   Pointer to rte_eth_dev structure.
   13099                 :            :  * @param[in] action
   13100                 :            :  *   Pointer to sample action structure.
   13101                 :            :  * @param[in, out] dev_flow
   13102                 :            :  *   Pointer to the mlx5_flow.
   13103                 :            :  * @param[in] attr
   13104                 :            :  *   Pointer to the flow attributes.
   13105                 :            :  * @param[in, out] num_of_dest
   13106                 :            :  *   Pointer to the num of destination.
   13107                 :            :  * @param[in, out] sample_actions
   13108                 :            :  *   Pointer to sample actions list.
   13109                 :            :  * @param[in, out] res
   13110                 :            :  *   Pointer to sample resource.
   13111                 :            :  * @param[out] error
   13112                 :            :  *   Pointer to the error structure.
   13113                 :            :  *
   13114                 :            :  * @return
   13115                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13116                 :            :  */
   13117                 :            : static int
   13118                 :          0 : flow_dv_translate_action_sample(struct rte_eth_dev *dev,
   13119                 :            :                                 const struct rte_flow_action_sample *action,
   13120                 :            :                                 struct mlx5_flow *dev_flow,
   13121                 :            :                                 const struct rte_flow_attr *attr,
   13122                 :            :                                 uint32_t *num_of_dest,
   13123                 :            :                                 void **sample_actions,
   13124                 :            :                                 struct mlx5_flow_dv_sample_resource *res,
   13125                 :            :                                 struct rte_flow_error *error)
   13126                 :            : {
   13127                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13128                 :            :         const struct rte_flow_action *sub_actions;
   13129                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   13130                 :            :         struct mlx5_flow_sub_actions_idx *sample_idx;
   13131                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   13132                 :          0 :         struct rte_flow *flow = dev_flow->flow;
   13133                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   13134                 :            :         uint64_t action_flags = 0;
   13135                 :            : 
   13136                 :            :         MLX5_ASSERT(wks);
   13137                 :          0 :         rss_desc = &wks->rss_desc;
   13138                 :            :         sample_act = &res->sample_act;
   13139                 :            :         sample_idx = &res->sample_idx;
   13140                 :          0 :         res->ratio = action->ratio;
   13141                 :          0 :         sub_actions = action->actions;
   13142         [ #  # ]:          0 :         for (; sub_actions->type != RTE_FLOW_ACTION_TYPE_END; sub_actions++) {
   13143                 :            :                 int type = sub_actions->type;
   13144                 :            :                 uint32_t pre_rix = 0;
   13145                 :            :                 void *pre_r;
   13146   [ #  #  #  #  :          0 :                 switch (type) {
                #  #  # ]
   13147                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   13148                 :            :                 {
   13149                 :            :                         const struct rte_flow_action_queue *queue;
   13150                 :            :                         struct mlx5_hrxq *hrxq;
   13151                 :            :                         uint32_t hrxq_idx;
   13152                 :            : 
   13153                 :          0 :                         queue = sub_actions->conf;
   13154                 :          0 :                         rss_desc->queue_num = 1;
   13155                 :          0 :                         rss_desc->queue[0] = queue->index;
   13156                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13157                 :            :                                                     rss_desc, &hrxq_idx);
   13158         [ #  # ]:          0 :                         if (!hrxq)
   13159                 :          0 :                                 return rte_flow_error_set
   13160                 :            :                                         (error, rte_errno,
   13161                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   13162                 :            :                                          NULL,
   13163                 :            :                                          "cannot create fate queue");
   13164                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13165                 :          0 :                         sample_idx->rix_hrxq = hrxq_idx;
   13166                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13167                 :            :                                                 hrxq->action;
   13168                 :          0 :                         (*num_of_dest)++;
   13169                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
   13170         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13171                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13172                 :          0 :                         dev_flow->handle->fate_action =
   13173                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   13174                 :          0 :                         break;
   13175                 :            :                 }
   13176                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   13177                 :            :                 {
   13178                 :            :                         struct mlx5_hrxq *hrxq;
   13179                 :            :                         uint32_t hrxq_idx;
   13180                 :            :                         const struct rte_flow_action_rss *rss;
   13181                 :            :                         const uint8_t *rss_key;
   13182                 :            : 
   13183                 :          0 :                         rss = sub_actions->conf;
   13184                 :          0 :                         rss_desc->symmetric_hash_function =
   13185                 :          0 :                                 MLX5_RSS_IS_SYMM(rss->func);
   13186                 :          0 :                         memcpy(rss_desc->queue, rss->queue,
   13187         [ #  # ]:          0 :                                rss->queue_num * sizeof(uint16_t));
   13188                 :          0 :                         rss_desc->queue_num = rss->queue_num;
   13189                 :            :                         /* NULL RSS key indicates default RSS key. */
   13190         [ #  # ]:          0 :                         rss_key = !rss->key ? mlx5_rss_hash_default_key : rss->key;
   13191                 :          0 :                         memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   13192                 :            :                         /*
   13193                 :            :                          * rss->level and rss.types should be set in advance
   13194                 :            :                          * when expanding items for RSS.
   13195                 :            :                          */
   13196                 :          0 :                         mlx5_flow_dv_hashfields_set(dev_flow->handle->layers,
   13197                 :            :                                                     rss_desc,
   13198                 :            :                                                     &dev_flow->hash_fields);
   13199                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13200                 :            :                                                     rss_desc, &hrxq_idx);
   13201         [ #  # ]:          0 :                         if (!hrxq)
   13202                 :          0 :                                 return rte_flow_error_set
   13203                 :            :                                         (error, rte_errno,
   13204                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   13205                 :            :                                          NULL,
   13206                 :            :                                          "cannot create fate queue");
   13207                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13208                 :          0 :                         sample_idx->rix_hrxq = hrxq_idx;
   13209                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13210                 :            :                                                 hrxq->action;
   13211                 :          0 :                         (*num_of_dest)++;
   13212                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
   13213         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13214                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13215                 :          0 :                         dev_flow->handle->fate_action =
   13216                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   13217                 :          0 :                         break;
   13218                 :            :                 }
   13219                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
   13220                 :            :                 {
   13221                 :            :                         uint32_t tag_be = mlx5_flow_mark_set
   13222                 :            :                                 (((const struct rte_flow_action_mark *)
   13223         [ #  # ]:          0 :                                 (sub_actions->conf))->id);
   13224                 :            : 
   13225                 :          0 :                         wks->mark = 1;
   13226                 :          0 :                         pre_rix = dev_flow->handle->dvh.rix_tag;
   13227                 :            :                         /* Save the mark resource before sample */
   13228                 :          0 :                         pre_r = dev_flow->dv.tag_resource;
   13229         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   13230                 :            :                                                   dev_flow, error))
   13231                 :          0 :                                 return -rte_errno;
   13232                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   13233                 :          0 :                         sample_act->dr_tag_action =
   13234                 :          0 :                                 dev_flow->dv.tag_resource->action;
   13235                 :          0 :                         sample_idx->rix_tag =
   13236                 :          0 :                                 dev_flow->handle->dvh.rix_tag;
   13237                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13238                 :            :                                                 sample_act->dr_tag_action;
   13239                 :            :                         /* Recover the mark resource after sample */
   13240                 :          0 :                         dev_flow->dv.tag_resource = pre_r;
   13241                 :          0 :                         dev_flow->handle->dvh.rix_tag = pre_rix;
   13242                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
   13243                 :          0 :                         break;
   13244                 :            :                 }
   13245                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   13246                 :            :                 {
   13247         [ #  # ]:          0 :                         if (!flow->counter) {
   13248                 :          0 :                                 flow->counter =
   13249                 :          0 :                                         flow_dv_translate_create_counter(dev,
   13250                 :          0 :                                                 dev_flow, sub_actions->conf,
   13251                 :            :                                                 0);
   13252         [ #  # ]:          0 :                                 if (!flow->counter)
   13253                 :          0 :                                         return rte_flow_error_set
   13254                 :            :                                                 (error, rte_errno,
   13255                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   13256                 :            :                                                 NULL,
   13257                 :            :                                                 "cannot create counter"
   13258                 :            :                                                 " object.");
   13259                 :            :                         }
   13260                 :          0 :                         sample_act->dr_cnt_action =
   13261         [ #  # ]:          0 :                                   (flow_dv_counter_get_by_idx(dev,
   13262                 :          0 :                                   flow->counter, NULL))->action;
   13263                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13264                 :            :                                                 sample_act->dr_cnt_action;
   13265                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
   13266                 :          0 :                         break;
   13267                 :            :                 }
   13268                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
   13269                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   13270                 :            :                 {
   13271                 :            :                         struct mlx5_flow_dv_port_id_action_resource
   13272                 :            :                                         port_id_resource;
   13273                 :          0 :                         uint32_t port_id = 0;
   13274                 :            : 
   13275                 :            :                         memset(&port_id_resource, 0, sizeof(port_id_resource));
   13276                 :            :                         /* Save the port id resource before sample */
   13277                 :          0 :                         pre_rix = dev_flow->handle->rix_port_id_action;
   13278                 :          0 :                         pre_r = dev_flow->dv.port_id_action;
   13279         [ #  # ]:          0 :                         if (flow_dv_translate_action_port_id(dev, sub_actions,
   13280                 :            :                                                              &port_id, error))
   13281                 :          0 :                                 return -rte_errno;
   13282                 :          0 :                         port_id_resource.port_id = port_id;
   13283         [ #  # ]:          0 :                         if (flow_dv_port_id_action_resource_register
   13284                 :            :                             (dev, &port_id_resource, dev_flow, error))
   13285                 :          0 :                                 return -rte_errno;
   13286                 :          0 :                         sample_act->dr_port_id_action =
   13287                 :          0 :                                 dev_flow->dv.port_id_action->action;
   13288                 :          0 :                         sample_idx->rix_port_id_action =
   13289                 :          0 :                                 dev_flow->handle->rix_port_id_action;
   13290                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13291                 :            :                                                 sample_act->dr_port_id_action;
   13292                 :            :                         /* Recover the port id resource after sample */
   13293                 :          0 :                         dev_flow->dv.port_id_action = pre_r;
   13294                 :          0 :                         dev_flow->handle->rix_port_id_action = pre_rix;
   13295                 :          0 :                         (*num_of_dest)++;
   13296                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   13297                 :          0 :                         break;
   13298                 :            :                 }
   13299                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   13300                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   13301                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   13302                 :            :                         /* Save the encap resource before sample */
   13303                 :          0 :                         pre_rix = dev_flow->handle->dvh.rix_encap_decap;
   13304                 :          0 :                         pre_r = dev_flow->dv.encap_decap;
   13305         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_encap(dev, sub_actions,
   13306                 :            :                                                            dev_flow,
   13307                 :          0 :                                                            attr->transfer,
   13308                 :            :                                                            error))
   13309                 :          0 :                                 return -rte_errno;
   13310                 :          0 :                         sample_act->dr_encap_action =
   13311                 :          0 :                                 dev_flow->dv.encap_decap->action;
   13312                 :          0 :                         sample_idx->rix_encap_decap =
   13313                 :          0 :                                 dev_flow->handle->dvh.rix_encap_decap;
   13314                 :          0 :                         sample_actions[sample_act->actions_num++] =
   13315                 :            :                                                 sample_act->dr_encap_action;
   13316                 :            :                         /* Recover the encap resource after sample */
   13317                 :          0 :                         dev_flow->dv.encap_decap = pre_r;
   13318                 :          0 :                         dev_flow->handle->dvh.rix_encap_decap = pre_rix;
   13319                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   13320                 :          0 :                         break;
   13321                 :          0 :                 default:
   13322                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13323                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   13324                 :            :                                 NULL,
   13325                 :            :                                 "Not support for sampler action");
   13326                 :            :                 }
   13327                 :            :         }
   13328                 :          0 :         sample_act->action_flags = action_flags;
   13329                 :          0 :         res->ft_id = dev_flow->dv.group;
   13330         [ #  # ]:          0 :         if (attr->transfer) {
   13331                 :            :                 union {
   13332                 :            :                         uint32_t action_in[MLX5_ST_SZ_DW(set_action_in)];
   13333                 :            :                         uint64_t set_action;
   13334                 :            :                 } action_ctx = { .set_action = 0 };
   13335                 :          0 :                 uint32_t vport_meta_tag = wks->vport_meta_tag ?
   13336         [ #  # ]:          0 :                                           wks->vport_meta_tag :
   13337                 :            :                                           priv->vport_meta_tag;
   13338                 :            : 
   13339                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
   13340                 :            :                 MLX5_SET(set_action_in, action_ctx.action_in, action_type,
   13341                 :            :                          MLX5_MODIFICATION_TYPE_SET);
   13342         [ #  # ]:          0 :                 MLX5_SET(set_action_in, action_ctx.action_in, field,
   13343                 :            :                          MLX5_MODI_META_REG_C_0);
   13344                 :          0 :                 MLX5_SET(set_action_in, action_ctx.action_in, data,
   13345                 :            :                          vport_meta_tag);
   13346                 :          0 :                 res->set_action = action_ctx.set_action;
   13347         [ #  # ]:          0 :         } else if (attr->ingress) {
   13348                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   13349                 :            :         } else {
   13350                 :          0 :                 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX;
   13351                 :            :         }
   13352                 :            :         return 0;
   13353                 :            : }
   13354                 :            : 
   13355                 :            : static void *
   13356                 :          0 : flow_dv_translate_action_send_to_kernel(struct rte_eth_dev *dev,
   13357                 :            :                                         const struct rte_flow_attr *attr,
   13358                 :            :                                         struct rte_flow_error *error)
   13359                 :            : {
   13360                 :            :         struct mlx5_flow_tbl_resource *tbl;
   13361                 :            :         struct mlx5_dev_ctx_shared *sh;
   13362                 :            :         uint32_t priority;
   13363                 :            :         void *action;
   13364                 :            :         int ft_type;
   13365                 :            :         int ret;
   13366                 :            : 
   13367                 :          0 :         sh = MLX5_SH(dev);
   13368         [ #  # ]:          0 :         ft_type = (attr->ingress) ? MLX5DR_TABLE_TYPE_NIC_RX :
   13369         [ #  # ]:          0 :                   ((attr->transfer) ? MLX5DR_TABLE_TYPE_FDB :
   13370                 :            :                   MLX5DR_TABLE_TYPE_NIC_TX);
   13371         [ #  # ]:          0 :         if (sh->send_to_kernel_action[ft_type].action)
   13372                 :            :                 return sh->send_to_kernel_action[ft_type].action;
   13373                 :          0 :         priority = mlx5_get_send_to_kernel_priority(dev);
   13374         [ #  # ]:          0 :         if (priority == (uint32_t)-1) {
   13375                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
   13376                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13377                 :            :                                    "required priority is not available");
   13378                 :          0 :                 return NULL;
   13379                 :            :         }
   13380                 :          0 :         tbl = mlx5_flow_dv_tbl_resource_get(dev, 0, attr->egress, attr->transfer,
   13381                 :            :                                             false, NULL, 0, 0, 0, error);
   13382         [ #  # ]:          0 :         if (!tbl) {
   13383                 :          0 :                 rte_flow_error_set(error, ENODATA,
   13384                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13385                 :            :                                    "cannot find destination root table");
   13386                 :          0 :                 return NULL;
   13387                 :            :         }
   13388                 :          0 :         ret = mlx5_flow_os_create_flow_action_send_to_kernel(tbl->obj,
   13389                 :            :                                 priority, &action);
   13390                 :            :         if (ret) {
   13391                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   13392                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   13393                 :            :                                    "cannot create action");
   13394                 :          0 :                 goto err;
   13395                 :            :         }
   13396                 :            :         MLX5_ASSERT(action);
   13397                 :          0 :         sh->send_to_kernel_action[ft_type].action = action;
   13398                 :          0 :         sh->send_to_kernel_action[ft_type].tbl = tbl;
   13399                 :          0 :         return action;
   13400                 :            : err:
   13401                 :          0 :         mlx5_flow_dv_tbl_resource_release(sh, tbl);
   13402                 :          0 :         return NULL;
   13403                 :            : }
   13404                 :            : 
   13405                 :            : /**
   13406                 :            :  * Convert Sample action to DV specification.
   13407                 :            :  *
   13408                 :            :  * @param[in] dev
   13409                 :            :  *   Pointer to rte_eth_dev structure.
   13410                 :            :  * @param[in, out] dev_flow
   13411                 :            :  *   Pointer to the mlx5_flow.
   13412                 :            :  * @param[in] num_of_dest
   13413                 :            :  *   The num of destination.
   13414                 :            :  * @param[in, out] res
   13415                 :            :  *   Pointer to sample resource.
   13416                 :            :  * @param[in, out] mdest_res
   13417                 :            :  *   Pointer to destination array resource.
   13418                 :            :  * @param[in] sample_actions
   13419                 :            :  *   Pointer to sample path actions list.
   13420                 :            :  * @param[in] action_flags
   13421                 :            :  *   Holds the actions detected until now.
   13422                 :            :  * @param[out] error
   13423                 :            :  *   Pointer to the error structure.
   13424                 :            :  *
   13425                 :            :  * @return
   13426                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   13427                 :            :  */
   13428                 :            : static int
   13429                 :          0 : flow_dv_create_action_sample(struct rte_eth_dev *dev,
   13430                 :            :                              struct mlx5_flow *dev_flow,
   13431                 :            :                              uint32_t num_of_dest,
   13432                 :            :                              struct mlx5_flow_dv_sample_resource *res,
   13433                 :            :                              struct mlx5_flow_dv_dest_array_resource *mdest_res,
   13434                 :            :                              void **sample_actions,
   13435                 :            :                              uint64_t action_flags,
   13436                 :            :                              struct rte_flow_error *error)
   13437                 :            : {
   13438                 :            :         /* update normal path action resource into last index of array */
   13439                 :            :         uint32_t dest_index = MLX5_MAX_DEST_NUM - 1;
   13440                 :            :         struct mlx5_flow_sub_actions_list *sample_act =
   13441                 :            :                                         &mdest_res->sample_act[dest_index];
   13442                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   13443                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   13444                 :            :         uint32_t normal_idx = 0;
   13445                 :            :         struct mlx5_hrxq *hrxq;
   13446                 :            :         uint32_t hrxq_idx;
   13447                 :            : 
   13448                 :            :         MLX5_ASSERT(wks);
   13449                 :          0 :         rss_desc = &wks->rss_desc;
   13450         [ #  # ]:          0 :         if (num_of_dest > 1) {
   13451         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_QUEUE) {
   13452                 :            :                         /* Handle QP action for mirroring */
   13453                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow,
   13454                 :            :                                                     rss_desc, &hrxq_idx);
   13455         [ #  # ]:          0 :                         if (!hrxq)
   13456                 :          0 :                                 return rte_flow_error_set
   13457                 :            :                                      (error, rte_errno,
   13458                 :            :                                       RTE_FLOW_ERROR_TYPE_ACTION,
   13459                 :            :                                       NULL,
   13460                 :            :                                       "cannot create rx queue");
   13461                 :            :                         normal_idx++;
   13462                 :          0 :                         mdest_res->sample_idx[dest_index].rix_hrxq = hrxq_idx;
   13463                 :          0 :                         sample_act->dr_queue_action = hrxq->action;
   13464         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_MARK)
   13465                 :          0 :                                 dev_flow->handle->rix_hrxq = hrxq_idx;
   13466                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
   13467                 :            :                 }
   13468         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_ENCAP) {
   13469                 :          0 :                         normal_idx++;
   13470                 :          0 :                         mdest_res->sample_idx[dest_index].rix_encap_decap =
   13471                 :          0 :                                 dev_flow->handle->dvh.rix_encap_decap;
   13472                 :          0 :                         sample_act->dr_encap_action =
   13473                 :          0 :                                 dev_flow->dv.encap_decap->action;
   13474                 :          0 :                         dev_flow->handle->dvh.rix_encap_decap = 0;
   13475                 :            :                 }
   13476         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_PORT_ID) {
   13477                 :          0 :                         normal_idx++;
   13478                 :          0 :                         mdest_res->sample_idx[dest_index].rix_port_id_action =
   13479                 :          0 :                                 dev_flow->handle->rix_port_id_action;
   13480                 :          0 :                         sample_act->dr_port_id_action =
   13481                 :          0 :                                 dev_flow->dv.port_id_action->action;
   13482                 :          0 :                         dev_flow->handle->rix_port_id_action = 0;
   13483                 :            :                 }
   13484         [ #  # ]:          0 :                 if (sample_act->action_flags & MLX5_FLOW_ACTION_JUMP) {
   13485                 :          0 :                         normal_idx++;
   13486                 :          0 :                         mdest_res->sample_idx[dest_index].rix_jump =
   13487                 :          0 :                                 dev_flow->handle->rix_jump;
   13488                 :          0 :                         sample_act->dr_jump_action =
   13489                 :          0 :                                 dev_flow->dv.jump->action;
   13490                 :          0 :                         dev_flow->handle->rix_jump = 0;
   13491                 :            :                 }
   13492                 :          0 :                 sample_act->actions_num = normal_idx;
   13493                 :            :                 /* update sample action resource into first index of array */
   13494                 :          0 :                 mdest_res->ft_type = res->ft_type;
   13495                 :          0 :                 memcpy(&mdest_res->sample_idx[0], &res->sample_idx,
   13496                 :            :                                 sizeof(struct mlx5_flow_sub_actions_idx));
   13497                 :          0 :                 memcpy(&mdest_res->sample_act[0], &res->sample_act,
   13498                 :            :                                 sizeof(struct mlx5_flow_sub_actions_list));
   13499                 :          0 :                 mdest_res->num_of_dest = num_of_dest;
   13500         [ #  # ]:          0 :                 if (flow_dv_dest_array_resource_register(dev, mdest_res,
   13501                 :            :                                                          dev_flow, error))
   13502                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13503                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   13504                 :            :                                                   NULL, "can't create sample "
   13505                 :            :                                                   "action");
   13506                 :            :         } else {
   13507                 :          0 :                 res->sub_actions = sample_actions;
   13508         [ #  # ]:          0 :                 if (flow_dv_sample_resource_register(dev, res, dev_flow, error))
   13509                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   13510                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   13511                 :            :                                                   NULL,
   13512                 :            :                                                   "can't create sample action");
   13513                 :            :         }
   13514                 :            :         return 0;
   13515                 :            : }
   13516                 :            : 
   13517                 :            : /**
   13518                 :            :  * Remove an ASO age action from age actions list.
   13519                 :            :  *
   13520                 :            :  * @param[in] dev
   13521                 :            :  *   Pointer to the Ethernet device structure.
   13522                 :            :  * @param[in] age
   13523                 :            :  *   Pointer to the aso age action handler.
   13524                 :            :  */
   13525                 :            : static void
   13526                 :          0 : flow_dv_aso_age_remove_from_age(struct rte_eth_dev *dev,
   13527                 :            :                                 struct mlx5_aso_age_action *age)
   13528                 :            : {
   13529                 :            :         struct mlx5_age_info *age_info;
   13530                 :            :         struct mlx5_age_param *age_param = &age->age_params;
   13531                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13532                 :            :         uint16_t expected = AGE_CANDIDATE;
   13533                 :            : 
   13534                 :          0 :         age_info = GET_PORT_AGE_INFO(priv);
   13535         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&age_param->state, &expected,
   13536                 :            :                                          AGE_FREE, rte_memory_order_relaxed,
   13537                 :            :                                          rte_memory_order_relaxed)) {
   13538                 :            :                 /**
   13539                 :            :                  * We need the lock even it is age timeout,
   13540                 :            :                  * since age action may still in process.
   13541                 :            :                  */
   13542                 :          0 :                 rte_spinlock_lock(&age_info->aged_sl);
   13543         [ #  # ]:          0 :                 LIST_REMOVE(age, next);
   13544                 :            :                 rte_spinlock_unlock(&age_info->aged_sl);
   13545                 :          0 :                 rte_atomic_store_explicit(&age_param->state, AGE_FREE, rte_memory_order_relaxed);
   13546                 :            :         }
   13547                 :          0 : }
   13548                 :            : 
   13549                 :            : /**
   13550                 :            :  * Release an ASO age action.
   13551                 :            :  *
   13552                 :            :  * @param[in] dev
   13553                 :            :  *   Pointer to the Ethernet device structure.
   13554                 :            :  * @param[in] age_idx
   13555                 :            :  *   Index of ASO age action to release.
   13556                 :            :  * @param[in] flow
   13557                 :            :  *   True if the release operation is during flow destroy operation.
   13558                 :            :  *   False if the release operation is during action destroy operation.
   13559                 :            :  *
   13560                 :            :  * @return
   13561                 :            :  *   0 when age action was removed, otherwise the number of references.
   13562                 :            :  */
   13563                 :            : static int
   13564                 :          0 : flow_dv_aso_age_release(struct rte_eth_dev *dev, uint32_t age_idx)
   13565                 :            : {
   13566                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13567                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13568                 :          0 :         struct mlx5_aso_age_action *age = mlx5_flow_aso_age_get_by_idx(dev, age_idx);
   13569                 :          0 :         uint32_t ret = rte_atomic_fetch_sub_explicit(&age->refcnt, 1, rte_memory_order_relaxed) - 1;
   13570                 :            : 
   13571         [ #  # ]:          0 :         if (!ret) {
   13572                 :          0 :                 flow_dv_aso_age_remove_from_age(dev, age);
   13573                 :          0 :                 rte_spinlock_lock(&mng->free_sl);
   13574         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free, age, next);
   13575                 :            :                 rte_spinlock_unlock(&mng->free_sl);
   13576                 :            :         }
   13577                 :          0 :         return ret;
   13578                 :            : }
   13579                 :            : 
   13580                 :            : /**
   13581                 :            :  * Resize the ASO age pools array by MLX5_ASO_AGE_CONTAINER_RESIZE pools.
   13582                 :            :  *
   13583                 :            :  * @param[in] dev
   13584                 :            :  *   Pointer to the Ethernet device structure.
   13585                 :            :  *
   13586                 :            :  * @return
   13587                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
   13588                 :            :  */
   13589                 :            : static int
   13590                 :          0 : flow_dv_aso_age_pools_resize(struct rte_eth_dev *dev)
   13591                 :            : {
   13592                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13593                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13594                 :          0 :         void *old_pools = mng->pools;
   13595                 :          0 :         uint32_t resize = mng->n + MLX5_ASO_AGE_CONTAINER_RESIZE;
   13596                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_age_pool *) * resize;
   13597                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   13598                 :            : 
   13599         [ #  # ]:          0 :         if (!pools) {
   13600                 :          0 :                 rte_errno = ENOMEM;
   13601                 :          0 :                 return -ENOMEM;
   13602                 :            :         }
   13603         [ #  # ]:          0 :         if (old_pools) {
   13604                 :          0 :                 memcpy(pools, old_pools,
   13605                 :          0 :                        mng->n * sizeof(struct mlx5_flow_counter_pool *));
   13606                 :          0 :                 mlx5_free(old_pools);
   13607                 :            :         } else {
   13608                 :            :                 /* First ASO flow hit allocation - starting ASO data-path. */
   13609                 :          0 :                 int ret = mlx5_aso_flow_hit_queue_poll_start(priv->sh);
   13610                 :            : 
   13611         [ #  # ]:          0 :                 if (ret) {
   13612                 :          0 :                         mlx5_free(pools);
   13613                 :          0 :                         return ret;
   13614                 :            :                 }
   13615                 :            :         }
   13616                 :          0 :         mng->n = resize;
   13617                 :          0 :         mng->pools = pools;
   13618                 :          0 :         return 0;
   13619                 :            : }
   13620                 :            : 
   13621                 :            : /**
   13622                 :            :  * Create and initialize a new ASO aging pool.
   13623                 :            :  *
   13624                 :            :  * @param[in] dev
   13625                 :            :  *   Pointer to the Ethernet device structure.
   13626                 :            :  * @param[out] age_free
   13627                 :            :  *   Where to put the pointer of a new age action.
   13628                 :            :  *
   13629                 :            :  * @return
   13630                 :            :  *   The age actions pool pointer and @p age_free is set on success,
   13631                 :            :  *   NULL otherwise and rte_errno is set.
   13632                 :            :  */
   13633                 :            : static struct mlx5_aso_age_pool *
   13634                 :          0 : flow_dv_age_pool_create(struct rte_eth_dev *dev,
   13635                 :            :                         struct mlx5_aso_age_action **age_free)
   13636                 :            : {
   13637                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13638                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13639                 :            :         struct mlx5_aso_age_pool *pool = NULL;
   13640                 :            :         struct mlx5_devx_obj *obj = NULL;
   13641                 :            :         uint32_t i;
   13642                 :            : 
   13643                 :          0 :         obj = mlx5_devx_cmd_create_flow_hit_aso_obj(priv->sh->cdev->ctx,
   13644                 :          0 :                                                     priv->sh->cdev->pdn);
   13645         [ #  # ]:          0 :         if (!obj) {
   13646                 :          0 :                 rte_errno = ENODATA;
   13647                 :          0 :                 DRV_LOG(ERR, "Failed to create flow_hit_aso_obj using DevX.");
   13648                 :          0 :                 return NULL;
   13649                 :            :         }
   13650                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY);
   13651         [ #  # ]:          0 :         if (!pool) {
   13652                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13653                 :          0 :                 rte_errno = ENOMEM;
   13654                 :          0 :                 return NULL;
   13655                 :            :         }
   13656                 :          0 :         pool->flow_hit_aso_obj = obj;
   13657                 :          0 :         pool->time_of_last_age_check = MLX5_CURR_TIME_SEC;
   13658                 :          0 :         rte_rwlock_write_lock(&mng->resize_rwl);
   13659                 :          0 :         pool->index = mng->next;
   13660                 :            :         /* Resize pools array if there is no room for the new pool in it. */
   13661   [ #  #  #  # ]:          0 :         if (pool->index == mng->n && flow_dv_aso_age_pools_resize(dev)) {
   13662                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   13663                 :          0 :                 mlx5_free(pool);
   13664                 :            :                 rte_rwlock_write_unlock(&mng->resize_rwl);
   13665                 :          0 :                 return NULL;
   13666                 :            :         }
   13667                 :          0 :         mng->pools[pool->index] = pool;
   13668                 :          0 :         mng->next++;
   13669                 :            :         rte_rwlock_write_unlock(&mng->resize_rwl);
   13670                 :            :         /* Assign the first action in the new pool, the rest go to free list. */
   13671                 :          0 :         *age_free = &pool->actions[0];
   13672         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_AGE_ACTIONS_PER_POOL; i++) {
   13673                 :          0 :                 pool->actions[i].offset = i;
   13674         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free, &pool->actions[i], next);
   13675                 :            :         }
   13676                 :            :         return pool;
   13677                 :            : }
   13678                 :            : 
   13679                 :            : /**
   13680                 :            :  * Allocate a ASO aging bit.
   13681                 :            :  *
   13682                 :            :  * @param[in] dev
   13683                 :            :  *   Pointer to the Ethernet device structure.
   13684                 :            :  * @param[out] error
   13685                 :            :  *   Pointer to the error structure.
   13686                 :            :  *
   13687                 :            :  * @return
   13688                 :            :  *   Index to ASO age action on success, 0 otherwise and rte_errno is set.
   13689                 :            :  */
   13690                 :            : static uint32_t
   13691                 :          0 : flow_dv_aso_age_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error)
   13692                 :            : {
   13693                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13694                 :            :         const struct mlx5_aso_age_pool *pool;
   13695                 :          0 :         struct mlx5_aso_age_action *age_free = NULL;
   13696                 :          0 :         struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
   13697                 :            : 
   13698                 :            :         MLX5_ASSERT(mng);
   13699                 :            :         /* Try to get the next free age action bit. */
   13700                 :          0 :         rte_spinlock_lock(&mng->free_sl);
   13701                 :          0 :         age_free = LIST_FIRST(&mng->free);
   13702         [ #  # ]:          0 :         if (age_free) {
   13703         [ #  # ]:          0 :                 LIST_REMOVE(age_free, next);
   13704         [ #  # ]:          0 :         } else if (!flow_dv_age_pool_create(dev, &age_free)) {
   13705                 :            :                 rte_spinlock_unlock(&mng->free_sl);
   13706                 :          0 :                 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
   13707                 :            :                                    NULL, "failed to create ASO age pool");
   13708                 :          0 :                 return 0; /* 0 is an error. */
   13709                 :            :         }
   13710                 :            :         rte_spinlock_unlock(&mng->free_sl);
   13711                 :          0 :         pool = container_of
   13712                 :            :           ((const struct mlx5_aso_age_action (*)[MLX5_ASO_AGE_ACTIONS_PER_POOL])
   13713                 :            :                   (age_free - age_free->offset), const struct mlx5_aso_age_pool,
   13714                 :            :                                                                        actions);
   13715         [ #  # ]:          0 :         if (!age_free->dr_action) {
   13716                 :          0 :                 int reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_FLOW_HIT, 0,
   13717                 :            :                                                  error);
   13718                 :            : 
   13719         [ #  # ]:          0 :                 if (reg_c < 0) {
   13720                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13721                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   13722                 :            :                                            NULL, "failed to get reg_c "
   13723                 :            :                                            "for ASO flow hit");
   13724                 :          0 :                         return 0; /* 0 is an error. */
   13725                 :            :                 }
   13726                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
   13727                 :          0 :                 age_free->dr_action = mlx5_glue->dv_create_flow_action_aso
   13728                 :          0 :                                 (priv->sh->rx_domain,
   13729                 :          0 :                                  pool->flow_hit_aso_obj->obj, age_free->offset,
   13730                 :            :                                  MLX5DV_DR_ACTION_FLAGS_ASO_FIRST_HIT_SET,
   13731                 :          0 :                                  (reg_c - REG_C_0));
   13732                 :            : #endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
   13733         [ #  # ]:          0 :                 if (!age_free->dr_action) {
   13734                 :          0 :                         rte_errno = errno;
   13735                 :            :                         rte_spinlock_lock(&mng->free_sl);
   13736         [ #  # ]:          0 :                         LIST_INSERT_HEAD(&mng->free, age_free, next);
   13737                 :            :                         rte_spinlock_unlock(&mng->free_sl);
   13738                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13739                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION,
   13740                 :            :                                            NULL, "failed to create ASO "
   13741                 :            :                                            "flow hit action");
   13742                 :          0 :                         return 0; /* 0 is an error. */
   13743                 :            :                 }
   13744                 :            :         }
   13745                 :          0 :         rte_atomic_store_explicit(&age_free->refcnt, 1, rte_memory_order_relaxed);
   13746                 :          0 :         return pool->index | ((age_free->offset + 1) << 16);
   13747                 :            : }
   13748                 :            : 
   13749                 :            : /**
   13750                 :            :  * Initialize flow ASO age parameters.
   13751                 :            :  *
   13752                 :            :  * @param[in] dev
   13753                 :            :  *   Pointer to rte_eth_dev structure.
   13754                 :            :  * @param[in] age_idx
   13755                 :            :  *   Index of ASO age action.
   13756                 :            :  * @param[in] context
   13757                 :            :  *   Pointer to flow counter age context.
   13758                 :            :  * @param[in] timeout
   13759                 :            :  *   Aging timeout in seconds.
   13760                 :            :  *
   13761                 :            :  */
   13762                 :            : static void
   13763                 :          0 : flow_dv_aso_age_params_init(struct rte_eth_dev *dev,
   13764                 :            :                             uint32_t age_idx,
   13765                 :            :                             void *context,
   13766                 :            :                             uint32_t timeout)
   13767                 :            : {
   13768                 :            :         struct mlx5_aso_age_action *aso_age;
   13769                 :            : 
   13770                 :          0 :         aso_age = mlx5_flow_aso_age_get_by_idx(dev, age_idx);
   13771                 :            :         MLX5_ASSERT(aso_age);
   13772                 :          0 :         aso_age->age_params.context = context;
   13773                 :          0 :         aso_age->age_params.timeout = timeout;
   13774                 :          0 :         aso_age->age_params.port_id = dev->data->port_id;
   13775                 :          0 :         rte_atomic_store_explicit(&aso_age->age_params.sec_since_last_hit, 0,
   13776                 :            :                          rte_memory_order_relaxed);
   13777                 :          0 :         rte_atomic_store_explicit(&aso_age->age_params.state, AGE_CANDIDATE,
   13778                 :            :                          rte_memory_order_relaxed);
   13779                 :          0 : }
   13780                 :            : 
   13781                 :            : static void
   13782                 :          0 : flow_dv_translate_integrity_l4(const struct rte_flow_item_integrity *mask,
   13783                 :            :                                void *headers)
   13784                 :            : {
   13785                 :            :         /*
   13786                 :            :          * In HWS mode MLX5_ITEM_UPDATE() macro assigns the same pointer to
   13787                 :            :          * both mask and value, therefore ether can be used.
   13788                 :            :          * In SWS SW_V mode mask points to item mask and value points to item
   13789                 :            :          * spec. Integrity item value is used only if matching mask is set.
   13790                 :            :          * Use mask reference here to keep SWS functionality.
   13791                 :            :          */
   13792         [ #  # ]:          0 :         if (mask->l4_ok) {
   13793                 :            :                 /* RTE l4_ok filter aggregates hardware l4_ok and
   13794                 :            :                  * l4_checksum_ok filters.
   13795                 :            :                  * Positive RTE l4_ok match requires hardware match on both L4
   13796                 :            :                  * hardware integrity bits.
   13797                 :            :                  * PMD supports positive integrity item semantics only.
   13798                 :            :                  */
   13799         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_ok, 1);
   13800         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_checksum_ok, 1);
   13801         [ #  # ]:          0 :         } else if (mask->l4_csum_ok) {
   13802         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l4_checksum_ok, 1);
   13803                 :            :         }
   13804                 :          0 : }
   13805                 :            : 
   13806                 :            : static void
   13807                 :          0 : flow_dv_translate_integrity_l3(const struct rte_flow_item_integrity *mask,
   13808                 :            :                                void *headers, bool is_ipv4)
   13809                 :            : {
   13810                 :            :         /*
   13811                 :            :          * In HWS mode MLX5_ITEM_UPDATE() macro assigns the same pointer to
   13812                 :            :          * both mask and value, therefore ether can be used.
   13813                 :            :          * In SWS SW_V mode mask points to item mask and value points to item
   13814                 :            :          * spec. Integrity item value used only if matching mask is set.
   13815                 :            :          * Use mask reference here to keep SWS functionality.
   13816                 :            :          */
   13817         [ #  # ]:          0 :         if (mask->l3_ok) {
   13818                 :            :                 /* RTE l3_ok filter aggregates for IPv4 hardware l3_ok and
   13819                 :            :                  * ipv4_csum_ok filters.
   13820                 :            :                  * Positive RTE l3_ok match requires hardware match on both L3
   13821                 :            :                  * hardware integrity bits.
   13822                 :            :                  * PMD supports positive integrity item semantics only.
   13823                 :            :                  */
   13824         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, l3_ok, 1);
   13825         [ #  # ]:          0 :                 if (is_ipv4) {
   13826         [ #  # ]:          0 :                         MLX5_SET(fte_match_set_lyr_2_4, headers,
   13827                 :            :                                  ipv4_checksum_ok, 1);
   13828                 :            :                 }
   13829   [ #  #  #  # ]:          0 :         } else if (is_ipv4 && mask->ipv4_csum_ok) {
   13830         [ #  # ]:          0 :                 MLX5_SET(fte_match_set_lyr_2_4, headers, ipv4_checksum_ok, 1);
   13831                 :            :         }
   13832                 :          0 : }
   13833                 :            : 
   13834                 :            : static void
   13835                 :          0 : set_integrity_bits(void *headers, const struct rte_flow_item *integrity_item,
   13836                 :            :                    bool is_l3_ip4, uint32_t key_type)
   13837                 :            : {
   13838                 :            :         const struct rte_flow_item_integrity *spec;
   13839                 :            :         const struct rte_flow_item_integrity *mask;
   13840                 :            : 
   13841                 :            :         /* Integrity bits validation cleared spec pointer */
   13842   [ #  #  #  #  :          0 :         if (MLX5_ITEM_VALID(integrity_item, key_type))
          #  #  #  #  #  
                      # ]
   13843                 :            :                 return;
   13844   [ #  #  #  #  :          0 :         MLX5_ITEM_UPDATE(integrity_item, key_type, spec, mask,
             #  #  #  # ]
   13845                 :            :                          &rte_flow_item_integrity_mask);
   13846                 :          0 :         flow_dv_translate_integrity_l3(mask, headers, is_l3_ip4);
   13847                 :          0 :         flow_dv_translate_integrity_l4(mask, headers);
   13848                 :            : }
   13849                 :            : 
   13850                 :            : static void
   13851                 :          0 : flow_dv_translate_item_integrity_post(void *key,
   13852                 :            :                                       const
   13853                 :            :                                       struct rte_flow_item *integrity_items[2],
   13854                 :            :                                       uint64_t pattern_flags, uint32_t key_type)
   13855                 :            : {
   13856                 :            :         void *headers;
   13857                 :            :         bool is_l3_ip4;
   13858                 :            : 
   13859         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_INNER_INTEGRITY) {
   13860                 :          0 :                 headers = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
   13861                 :          0 :                 is_l3_ip4 = (pattern_flags & MLX5_FLOW_LAYER_INNER_L3_IPV4) !=
   13862                 :            :                             0;
   13863                 :          0 :                 set_integrity_bits(headers, integrity_items[1], is_l3_ip4,
   13864                 :            :                                    key_type);
   13865                 :            :         }
   13866         [ #  # ]:          0 :         if (pattern_flags & MLX5_FLOW_ITEM_OUTER_INTEGRITY) {
   13867                 :            :                 headers = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
   13868                 :          0 :                 is_l3_ip4 = (pattern_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4) !=
   13869                 :            :                             0;
   13870                 :          0 :                 set_integrity_bits(headers, integrity_items[0], is_l3_ip4,
   13871                 :            :                                    key_type);
   13872                 :            :         }
   13873                 :          0 : }
   13874                 :            : 
   13875                 :            : static uint64_t
   13876                 :            : flow_dv_translate_item_integrity(const struct rte_flow_item *item,
   13877                 :            :                                  struct mlx5_dv_matcher_workspace *wks,
   13878                 :            :                                  uint64_t key_type)
   13879                 :            : {
   13880                 :          0 :         if ((key_type & MLX5_SET_MATCHER_SW) != 0) {
   13881                 :            :                 const struct rte_flow_item_integrity
   13882                 :          0 :                         *spec = (typeof(spec))item->spec;
   13883                 :            : 
   13884                 :            :                 /* SWS integrity bits validation cleared spec pointer */
   13885         [ #  # ]:          0 :                 if (spec->level > 1) {
   13886                 :          0 :                         wks->integrity_items[1] = item;
   13887                 :          0 :                         wks->last_item |= MLX5_FLOW_ITEM_INNER_INTEGRITY;
   13888                 :            :                 } else {
   13889                 :          0 :                         wks->integrity_items[0] = item;
   13890                 :          0 :                         wks->last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
   13891                 :            :                 }
   13892                 :            :         } else {
   13893                 :            :                 /* HWS supports outer integrity only */
   13894                 :          0 :                 wks->integrity_items[0] = item;
   13895                 :          0 :                 wks->last_item |= MLX5_FLOW_ITEM_OUTER_INTEGRITY;
   13896                 :            :         }
   13897                 :          0 :         return wks->last_item;
   13898                 :            : }
   13899                 :            : 
   13900                 :            : /**
   13901                 :            :  * Prepares DV flow counter with aging configuration.
   13902                 :            :  * Gets it by index when exists, creates a new one when doesn't.
   13903                 :            :  *
   13904                 :            :  * @param[in] dev
   13905                 :            :  *   Pointer to rte_eth_dev structure.
   13906                 :            :  * @param[in] dev_flow
   13907                 :            :  *   Pointer to the mlx5_flow.
   13908                 :            :  * @param[in, out] flow
   13909                 :            :  *   Pointer to the sub flow.
   13910                 :            :  * @param[in] count
   13911                 :            :  *   Pointer to the counter action configuration.
   13912                 :            :  * @param[in] age
   13913                 :            :  *   Pointer to the aging action configuration.
   13914                 :            :  * @param[out] error
   13915                 :            :  *   Pointer to the error structure.
   13916                 :            :  *
   13917                 :            :  * @return
   13918                 :            :  *   Pointer to the counter, NULL otherwise.
   13919                 :            :  */
   13920                 :            : static struct mlx5_flow_counter *
   13921                 :          0 : flow_dv_prepare_counter(struct rte_eth_dev *dev,
   13922                 :            :                         struct mlx5_flow *dev_flow,
   13923                 :            :                         struct rte_flow *flow,
   13924                 :            :                         const struct rte_flow_action_count *count,
   13925                 :            :                         const struct rte_flow_action_age *age,
   13926                 :            :                         struct rte_flow_error *error)
   13927                 :            : {
   13928         [ #  # ]:          0 :         if (!flow->counter) {
   13929                 :          0 :                 flow->counter = flow_dv_translate_create_counter(dev, dev_flow,
   13930                 :            :                                                                  count, age);
   13931         [ #  # ]:          0 :                 if (!flow->counter) {
   13932                 :          0 :                         rte_flow_error_set(error, rte_errno,
   13933                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   13934                 :            :                                            "cannot create counter object.");
   13935                 :          0 :                         return NULL;
   13936                 :            :                 }
   13937                 :            :         }
   13938         [ #  # ]:          0 :         return flow_dv_counter_get_by_idx(dev, flow->counter, NULL);
   13939                 :            : }
   13940                 :            : 
   13941                 :            : /*
   13942                 :            :  * Release an ASO CT action by its own device.
   13943                 :            :  *
   13944                 :            :  * @param[in] dev
   13945                 :            :  *   Pointer to the Ethernet device structure.
   13946                 :            :  * @param[in] idx
   13947                 :            :  *   Index of ASO CT action to release.
   13948                 :            :  *
   13949                 :            :  * @return
   13950                 :            :  *   0 when CT action was removed, otherwise the number of references.
   13951                 :            :  */
   13952                 :            : static inline int
   13953                 :          0 : flow_dv_aso_ct_dev_release(struct rte_eth_dev *dev, uint32_t idx)
   13954                 :            : {
   13955                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   13956                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   13957                 :            :         uint32_t ret;
   13958                 :          0 :         struct mlx5_aso_ct_action *ct = flow_aso_ct_get_by_dev_idx(dev, idx);
   13959                 :            :         enum mlx5_aso_ct_state state =
   13960                 :          0 :                         rte_atomic_load_explicit(&ct->state, rte_memory_order_relaxed);
   13961                 :            : 
   13962                 :            :         /* Cannot release when CT is in the ASO SQ. */
   13963         [ #  # ]:          0 :         if (state == ASO_CONNTRACK_WAIT || state == ASO_CONNTRACK_QUERY)
   13964                 :            :                 return -1;
   13965                 :          0 :         ret = rte_atomic_fetch_sub_explicit(&ct->refcnt, 1, rte_memory_order_relaxed) - 1;
   13966         [ #  # ]:          0 :         if (!ret) {
   13967         [ #  # ]:          0 :                 if (ct->dr_action_orig) {
   13968                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13969                 :          0 :                         claim_zero(mlx5_glue->destroy_flow_action
   13970                 :            :                                         (ct->dr_action_orig));
   13971                 :            : #endif
   13972                 :          0 :                         ct->dr_action_orig = NULL;
   13973                 :            :                 }
   13974         [ #  # ]:          0 :                 if (ct->dr_action_rply) {
   13975                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   13976                 :          0 :                         claim_zero(mlx5_glue->destroy_flow_action
   13977                 :            :                                         (ct->dr_action_rply));
   13978                 :            : #endif
   13979                 :          0 :                         ct->dr_action_rply = NULL;
   13980                 :            :                 }
   13981                 :            :                 /* Clear the state to free, no need in 1st allocation. */
   13982                 :          0 :                 MLX5_ASO_CT_UPDATE_STATE(ct, ASO_CONNTRACK_FREE);
   13983                 :          0 :                 rte_spinlock_lock(&mng->ct_sl);
   13984         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free_cts, ct, next);
   13985                 :            :                 rte_spinlock_unlock(&mng->ct_sl);
   13986                 :            :         }
   13987                 :          0 :         return (int)ret;
   13988                 :            : }
   13989                 :            : 
   13990                 :            : static inline int
   13991                 :          0 : flow_dv_aso_ct_release(struct rte_eth_dev *dev, uint32_t own_idx,
   13992                 :            :                        struct rte_flow_error *error)
   13993                 :            : {
   13994                 :          0 :         uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(own_idx);
   13995                 :          0 :         uint32_t idx = MLX5_INDIRECT_ACT_CT_GET_IDX(own_idx);
   13996                 :          0 :         struct rte_eth_dev *owndev = &rte_eth_devices[owner];
   13997                 :            :         int ret;
   13998                 :            : 
   13999                 :            :         MLX5_ASSERT(owner < RTE_MAX_ETHPORTS);
   14000         [ #  # ]:          0 :         if (dev->data->dev_started != 1)
   14001                 :          0 :                 return rte_flow_error_set(error, EAGAIN,
   14002                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   14003                 :            :                                           NULL,
   14004                 :            :                                           "Indirect CT action cannot be destroyed when the port is stopped");
   14005                 :          0 :         ret = flow_dv_aso_ct_dev_release(owndev, idx);
   14006         [ #  # ]:          0 :         if (ret < 0)
   14007                 :          0 :                 return rte_flow_error_set(error, EAGAIN,
   14008                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   14009                 :            :                                           NULL,
   14010                 :            :                                           "Current state prevents indirect CT action from being destroyed");
   14011                 :            :         return ret;
   14012                 :            : }
   14013                 :            : 
   14014                 :            : /*
   14015                 :            :  * Resize the ASO CT pools array by 64 pools.
   14016                 :            :  *
   14017                 :            :  * @param[in] dev
   14018                 :            :  *   Pointer to the Ethernet device structure.
   14019                 :            :  *
   14020                 :            :  * @return
   14021                 :            :  *   0 on success, otherwise negative errno value and rte_errno is set.
   14022                 :            :  */
   14023                 :            : static int
   14024                 :          0 : flow_dv_aso_ct_pools_resize(struct rte_eth_dev *dev)
   14025                 :            : {
   14026                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14027                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   14028                 :          0 :         void *old_pools = mng->pools;
   14029                 :            :         /* Magic number now, need a macro. */
   14030                 :          0 :         uint32_t resize = mng->n + 64;
   14031                 :          0 :         uint32_t mem_size = sizeof(struct mlx5_aso_ct_pool *) * resize;
   14032                 :          0 :         void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   14033                 :            : 
   14034         [ #  # ]:          0 :         if (!pools) {
   14035                 :          0 :                 rte_errno = ENOMEM;
   14036                 :          0 :                 return -rte_errno;
   14037                 :            :         }
   14038                 :          0 :         rte_rwlock_write_lock(&mng->resize_rwl);
   14039                 :            :         /* ASO SQ/QP was already initialized in the startup. */
   14040         [ #  # ]:          0 :         if (old_pools) {
   14041                 :            :                 /* Realloc could be an alternative choice. */
   14042                 :          0 :                 rte_memcpy(pools, old_pools,
   14043         [ #  # ]:          0 :                            mng->n * sizeof(struct mlx5_aso_ct_pool *));
   14044                 :          0 :                 mlx5_free(old_pools);
   14045                 :            :         }
   14046                 :          0 :         mng->n = resize;
   14047                 :          0 :         mng->pools = pools;
   14048                 :            :         rte_rwlock_write_unlock(&mng->resize_rwl);
   14049                 :          0 :         return 0;
   14050                 :            : }
   14051                 :            : 
   14052                 :            : /*
   14053                 :            :  * Create and initialize a new ASO CT pool.
   14054                 :            :  *
   14055                 :            :  * @param[in] dev
   14056                 :            :  *   Pointer to the Ethernet device structure.
   14057                 :            :  * @param[out] ct_free
   14058                 :            :  *   Where to put the pointer of a new CT action.
   14059                 :            :  *
   14060                 :            :  * @return
   14061                 :            :  *   The CT actions pool pointer and @p ct_free is set on success,
   14062                 :            :  *   NULL otherwise and rte_errno is set.
   14063                 :            :  */
   14064                 :            : static struct mlx5_aso_ct_pool *
   14065                 :          0 : flow_dv_ct_pool_create(struct rte_eth_dev *dev,
   14066                 :            :                        struct mlx5_aso_ct_action **ct_free)
   14067                 :            : {
   14068                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14069                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   14070                 :            :         struct mlx5_aso_ct_pool *pool = NULL;
   14071                 :            :         struct mlx5_devx_obj *obj = NULL;
   14072                 :            :         uint32_t i;
   14073                 :            :         uint32_t log_obj_size = rte_log2_u32(MLX5_ASO_CT_ACTIONS_PER_POOL);
   14074                 :            :         size_t mem_size;
   14075                 :            : 
   14076                 :          0 :         obj = mlx5_devx_cmd_create_conn_track_offload_obj(priv->sh->cdev->ctx,
   14077                 :          0 :                                                           priv->sh->cdev->pdn,
   14078                 :            :                                                           log_obj_size);
   14079         [ #  # ]:          0 :         if (!obj) {
   14080                 :          0 :                 rte_errno = ENODATA;
   14081                 :          0 :                 DRV_LOG(ERR, "Failed to create conn_track_offload_obj using DevX.");
   14082                 :          0 :                 return NULL;
   14083                 :            :         }
   14084                 :            :         mem_size = sizeof(struct mlx5_aso_ct_action) *
   14085                 :            :                    MLX5_ASO_CT_ACTIONS_PER_POOL +
   14086                 :            :                    sizeof(*pool);
   14087                 :          0 :         pool = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY);
   14088         [ #  # ]:          0 :         if (!pool) {
   14089                 :          0 :                 rte_errno = ENOMEM;
   14090                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   14091                 :          0 :                 return NULL;
   14092                 :            :         }
   14093                 :          0 :         pool->devx_obj = obj;
   14094                 :          0 :         pool->index = mng->next;
   14095                 :            :         /* Resize pools array if there is no room for the new pool in it. */
   14096   [ #  #  #  # ]:          0 :         if (pool->index == mng->n && flow_dv_aso_ct_pools_resize(dev)) {
   14097                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(obj));
   14098                 :          0 :                 mlx5_free(pool);
   14099                 :          0 :                 return NULL;
   14100                 :            :         }
   14101                 :          0 :         mng->pools[pool->index] = pool;
   14102                 :          0 :         mng->next++;
   14103                 :            :         /* Assign the first action in the new pool, the rest go to free list. */
   14104                 :          0 :         *ct_free = &pool->actions[0];
   14105                 :            :         /* Lock outside, the list operation is safe here. */
   14106         [ #  # ]:          0 :         for (i = 1; i < MLX5_ASO_CT_ACTIONS_PER_POOL; i++) {
   14107                 :            :                 /* refcnt is 0 when allocating the memory. */
   14108                 :          0 :                 pool->actions[i].offset = i;
   14109         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&mng->free_cts, &pool->actions[i], next);
   14110                 :            :         }
   14111                 :            :         return pool;
   14112                 :            : }
   14113                 :            : 
   14114                 :            : /*
   14115                 :            :  * Allocate a ASO CT action from free list.
   14116                 :            :  *
   14117                 :            :  * @param[in] dev
   14118                 :            :  *   Pointer to the Ethernet device structure.
   14119                 :            :  * @param[out] error
   14120                 :            :  *   Pointer to the error structure.
   14121                 :            :  *
   14122                 :            :  * @return
   14123                 :            :  *   Index to ASO CT action on success, 0 otherwise and rte_errno is set.
   14124                 :            :  */
   14125                 :            : static uint32_t
   14126                 :          0 : flow_dv_aso_ct_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error)
   14127                 :            : {
   14128                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14129                 :          0 :         struct mlx5_aso_ct_pools_mng *mng = priv->sh->ct_mng;
   14130                 :          0 :         struct mlx5_aso_ct_action *ct = NULL;
   14131                 :            :         struct mlx5_aso_ct_pool *pool;
   14132                 :            :         uint8_t reg_c;
   14133                 :            :         uint32_t ct_idx;
   14134                 :            : 
   14135                 :            :         MLX5_ASSERT(mng);
   14136         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx) {
   14137                 :          0 :                 rte_errno = ENOTSUP;
   14138                 :          0 :                 return 0;
   14139                 :            :         }
   14140                 :            :         /* Get a free CT action, if no, a new pool will be created. */
   14141                 :          0 :         rte_spinlock_lock(&mng->ct_sl);
   14142                 :          0 :         ct = LIST_FIRST(&mng->free_cts);
   14143         [ #  # ]:          0 :         if (ct) {
   14144         [ #  # ]:          0 :                 LIST_REMOVE(ct, next);
   14145         [ #  # ]:          0 :         } else if (!flow_dv_ct_pool_create(dev, &ct)) {
   14146                 :            :                 rte_spinlock_unlock(&mng->ct_sl);
   14147                 :          0 :                 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION,
   14148                 :            :                                    NULL, "failed to create ASO CT pool");
   14149                 :          0 :                 return 0;
   14150                 :            :         }
   14151                 :            :         rte_spinlock_unlock(&mng->ct_sl);
   14152                 :          0 :         pool = container_of(ct, struct mlx5_aso_ct_pool, actions[ct->offset]);
   14153                 :          0 :         ct_idx = MLX5_MAKE_CT_IDX(pool->index, ct->offset);
   14154                 :            :         /* 0: inactive, 1: created, 2+: used by flows. */
   14155                 :          0 :         rte_atomic_store_explicit(&ct->refcnt, 1, rte_memory_order_relaxed);
   14156                 :          0 :         reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_CONNTRACK, 0, error);
   14157         [ #  # ]:          0 :         if (!ct->dr_action_orig) {
   14158                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   14159                 :          0 :                 ct->dr_action_orig = mlx5_glue->dv_create_flow_action_aso
   14160                 :          0 :                         (priv->sh->rx_domain, pool->devx_obj->obj,
   14161                 :            :                          ct->offset,
   14162                 :            :                          MLX5DV_DR_ACTION_FLAGS_ASO_CT_DIRECTION_INITIATOR,
   14163                 :          0 :                          reg_c - REG_C_0);
   14164                 :            : #else
   14165                 :            :                 RTE_SET_USED(reg_c);
   14166                 :            : #endif
   14167         [ #  # ]:          0 :                 if (!ct->dr_action_orig) {
   14168                 :          0 :                         flow_dv_aso_ct_dev_release(dev, ct_idx);
   14169                 :          0 :                         rte_flow_error_set(error, rte_errno,
   14170                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14171                 :            :                                            "failed to create ASO CT action");
   14172                 :          0 :                         return 0;
   14173                 :            :                 }
   14174                 :            :         }
   14175         [ #  # ]:          0 :         if (!ct->dr_action_rply) {
   14176                 :            : #ifdef HAVE_MLX5_DR_ACTION_ASO_CT
   14177                 :          0 :                 ct->dr_action_rply = mlx5_glue->dv_create_flow_action_aso
   14178                 :          0 :                         (priv->sh->rx_domain, pool->devx_obj->obj,
   14179                 :            :                          ct->offset,
   14180                 :            :                          MLX5DV_DR_ACTION_FLAGS_ASO_CT_DIRECTION_RESPONDER,
   14181                 :          0 :                          reg_c - REG_C_0);
   14182                 :            : #endif
   14183         [ #  # ]:          0 :                 if (!ct->dr_action_rply) {
   14184                 :          0 :                         flow_dv_aso_ct_dev_release(dev, ct_idx);
   14185                 :          0 :                         rte_flow_error_set(error, rte_errno,
   14186                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14187                 :            :                                            "failed to create ASO CT action");
   14188                 :          0 :                         return 0;
   14189                 :            :                 }
   14190                 :            :         }
   14191                 :            :         return ct_idx;
   14192                 :            : }
   14193                 :            : 
   14194                 :            : /*
   14195                 :            :  * Create a conntrack object with context and actions by using ASO mechanism.
   14196                 :            :  *
   14197                 :            :  * @param[in] dev
   14198                 :            :  *   Pointer to rte_eth_dev structure.
   14199                 :            :  * @param[in] pro
   14200                 :            :  *   Pointer to conntrack information profile.
   14201                 :            :  * @param[out] error
   14202                 :            :  *   Pointer to the error structure.
   14203                 :            :  *
   14204                 :            :  * @return
   14205                 :            :  *   Index to conntrack object on success, 0 otherwise.
   14206                 :            :  */
   14207                 :            : static uint32_t
   14208                 :          0 : flow_dv_translate_create_conntrack(struct rte_eth_dev *dev,
   14209                 :            :                                    const struct rte_flow_action_conntrack *pro,
   14210                 :            :                                    struct rte_flow_error *error)
   14211                 :            : {
   14212                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14213                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   14214                 :            :         struct mlx5_aso_ct_action *ct;
   14215                 :            :         uint32_t idx;
   14216                 :            : 
   14217         [ #  # ]:          0 :         if (!sh->ct_aso_en)
   14218                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   14219                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14220                 :            :                                           "Connection is not supported");
   14221         [ #  # ]:          0 :         if (dev->data->port_id >= MLX5_INDIRECT_ACT_CT_MAX_PORT) {
   14222                 :          0 :                 rte_flow_error_set(error, EINVAL,
   14223                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   14224                 :            :                                    "CT supports port indexes up to "
   14225                 :            :                                    RTE_STR(MLX5_ACTION_CTX_CT_MAX_PORT));
   14226                 :          0 :                 return 0;
   14227                 :            :         }
   14228                 :          0 :         idx = flow_dv_aso_ct_alloc(dev, error);
   14229         [ #  # ]:          0 :         if (!idx)
   14230                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   14231                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14232                 :            :                                           "Failed to allocate CT object");
   14233                 :          0 :         ct = flow_aso_ct_get_by_dev_idx(dev, idx);
   14234         [ #  # ]:          0 :         if (mlx5_aso_ct_update_by_wqe(sh, MLX5_HW_INV_QUEUE, ct, pro, NULL, true)) {
   14235                 :          0 :                 flow_dv_aso_ct_dev_release(dev, idx);
   14236                 :          0 :                 rte_flow_error_set(error, EBUSY,
   14237                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   14238                 :            :                                    "Failed to update CT");
   14239                 :          0 :                 return 0;
   14240                 :            :         }
   14241                 :          0 :         ct->is_original = !!pro->is_original_dir;
   14242                 :          0 :         ct->peer = pro->peer_port;
   14243                 :          0 :         return idx;
   14244                 :            : }
   14245                 :            : 
   14246                 :            : /**
   14247                 :            :  * Fill the flow matcher with DV spec.
   14248                 :            :  *
   14249                 :            :  * @param[in] dev
   14250                 :            :  *   Pointer to rte_eth_dev structure.
   14251                 :            :  * @param[in] items
   14252                 :            :  *   Pointer to the list of items.
   14253                 :            :  * @param[in] wks
   14254                 :            :  *   Pointer to the matcher workspace.
   14255                 :            :  * @param[in] key
   14256                 :            :  *   Pointer to the flow matcher key.
   14257                 :            :  * @param[in] key_type
   14258                 :            :  *   Key type.
   14259                 :            :  * @param[out] error
   14260                 :            :  *   Pointer to the error structure.
   14261                 :            :  *
   14262                 :            :  * @return
   14263                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14264                 :            :  */
   14265                 :            : static int
   14266                 :          0 : flow_dv_translate_items(struct rte_eth_dev *dev,
   14267                 :            :                         const struct rte_flow_item *items,
   14268                 :            :                         struct mlx5_dv_matcher_workspace *wks,
   14269                 :            :                         void *key, uint32_t key_type,
   14270                 :            :                         struct rte_flow_error *error)
   14271                 :            : {
   14272                 :          0 :         struct mlx5_flow_rss_desc *rss_desc = wks->rss_desc;
   14273                 :          0 :         uint8_t next_protocol = wks->next_protocol;
   14274                 :          0 :         int tunnel = !!(wks->item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14275                 :          0 :         int item_type = items->type;
   14276                 :          0 :         uint64_t last_item = wks->last_item;
   14277                 :            :         enum mlx5_l3_tunnel_detection l3_tunnel_detection;
   14278                 :            :         uint64_t l3_tunnel_flag;
   14279                 :            :         int ret;
   14280                 :            : 
   14281   [ #  #  #  #  :          0 :         switch (item_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
   14282                 :          0 :         case RTE_FLOW_ITEM_TYPE_ESP:
   14283                 :          0 :                 flow_dv_translate_item_esp(key, items, tunnel, key_type, wks->item_flags);
   14284                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14285                 :            :                 last_item = MLX5_FLOW_ITEM_ESP;
   14286                 :          0 :                 break;
   14287                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_ID:
   14288                 :          0 :                 flow_dv_translate_item_port_id
   14289                 :            :                         (dev, key, items, wks->attr, key_type);
   14290                 :            :                 last_item = MLX5_FLOW_ITEM_PORT_ID;
   14291                 :          0 :                 break;
   14292                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
   14293                 :          0 :                 flow_dv_translate_item_port_representor
   14294                 :            :                         (dev, key, key_type);
   14295                 :            :                 last_item = MLX5_FLOW_ITEM_PORT_REPRESENTOR;
   14296                 :          0 :                 break;
   14297                 :          0 :         case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
   14298                 :          0 :                 flow_dv_translate_item_represented_port
   14299                 :            :                         (dev, key, items, wks->attr, key_type);
   14300                 :            :                 last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
   14301                 :          0 :                 break;
   14302                 :          0 :         case RTE_FLOW_ITEM_TYPE_ETH:
   14303                 :          0 :                 flow_dv_translate_item_eth(key, items, tunnel,
   14304                 :            :                                            wks->group, key_type);
   14305         [ #  # ]:          0 :                 wks->priority = wks->action_flags &
   14306                 :          0 :                                 MLX5_FLOW_ACTION_DEFAULT_MISS &&
   14307         [ #  # ]:          0 :                                 !wks->external ?
   14308                 :            :                                 MLX5_PRIORITY_MAP_L3 :
   14309                 :            :                                 MLX5_PRIORITY_MAP_L2;
   14310         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
   14311                 :            :                                      MLX5_FLOW_LAYER_OUTER_L2;
   14312                 :            :                 break;
   14313                 :          0 :         case RTE_FLOW_ITEM_TYPE_VLAN:
   14314                 :          0 :                 flow_dv_translate_item_vlan(key, items, tunnel, wks, key_type);
   14315                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L2;
   14316                 :            :                 last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
   14317         [ #  # ]:          0 :                                           MLX5_FLOW_LAYER_INNER_VLAN) :
   14318                 :            :                                          (MLX5_FLOW_LAYER_OUTER_L2 |
   14319                 :            :                                           MLX5_FLOW_LAYER_OUTER_VLAN);
   14320                 :            :                 break;
   14321                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:
   14322                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14323                 :            :                 l3_tunnel_detection =
   14324                 :            :                         mlx5_flow_tunnel_ip_check(items, next_protocol,
   14325                 :            :                                                   wks->item_flags,
   14326                 :            :                                                   &l3_tunnel_flag);
   14327                 :            :                 if (l3_tunnel_detection == l3_tunnel_inner) {
   14328                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14329                 :            :                         tunnel = 1;
   14330                 :            :                 }
   14331                 :          0 :                 flow_dv_translate_item_ipv4(key, items, tunnel,
   14332                 :            :                                             wks->group, key_type);
   14333                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L3;
   14334         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
   14335                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV4;
   14336         [ #  # ]:          0 :                 if (l3_tunnel_detection == l3_tunnel_outer)
   14337                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14338                 :            :                 break;
   14339                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:
   14340                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14341                 :            :                 l3_tunnel_detection =
   14342                 :            :                         mlx5_flow_tunnel_ip_check(items, next_protocol,
   14343                 :            :                                                   wks->item_flags,
   14344                 :            :                                                   &l3_tunnel_flag);
   14345                 :            :                 if (l3_tunnel_detection == l3_tunnel_inner) {
   14346                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14347                 :            :                         tunnel = 1;
   14348                 :            :                 }
   14349                 :          0 :                 flow_dv_translate_item_ipv6(key, items, tunnel,
   14350                 :            :                                             wks->group, key_type);
   14351                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L3;
   14352         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
   14353                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV6;
   14354         [ #  # ]:          0 :                 if (l3_tunnel_detection == l3_tunnel_outer)
   14355                 :          0 :                         wks->item_flags |= l3_tunnel_flag;
   14356                 :            :                 break;
   14357                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
   14358                 :          0 :                 flow_dv_translate_item_ipv6_frag_ext
   14359                 :            :                                         (key, items, tunnel, key_type);
   14360         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT :
   14361                 :            :                                      MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT;
   14362                 :            :                 next_protocol = mlx5_flow_l3_next_protocol(items, key_type);
   14363                 :            :                 break;
   14364                 :          0 :         case RTE_FLOW_ITEM_TYPE_TCP:
   14365                 :          0 :                 flow_dv_translate_item_tcp(key, items, tunnel, key_type);
   14366                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14367         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
   14368                 :            :                                      MLX5_FLOW_LAYER_OUTER_L4_TCP;
   14369                 :            :                 break;
   14370                 :          0 :         case RTE_FLOW_ITEM_TYPE_UDP:
   14371                 :          0 :                 flow_dv_translate_item_udp(key, items, tunnel, wks, key_type);
   14372                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14373         [ #  # ]:          0 :                 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
   14374                 :            :                                      MLX5_FLOW_LAYER_OUTER_L4_UDP;
   14375                 :            :                 break;
   14376                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE:
   14377         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14378                 :          0 :                 wks->tunnel_item = items;
   14379                 :          0 :                 wks->gre_item = items;
   14380                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14381                 :          0 :                 break;
   14382                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_KEY:
   14383                 :          0 :                 flow_dv_translate_item_gre_key(key, items, key_type);
   14384                 :            :                 last_item = MLX5_FLOW_LAYER_GRE_KEY;
   14385                 :          0 :                 break;
   14386                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
   14387         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14388                 :          0 :                 wks->tunnel_item = items;
   14389                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14390                 :          0 :                 break;
   14391                 :          0 :         case RTE_FLOW_ITEM_TYPE_NVGRE:
   14392         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14393                 :          0 :                 wks->tunnel_item = items;
   14394                 :            :                 last_item = MLX5_FLOW_LAYER_GRE;
   14395                 :          0 :                 break;
   14396                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN:
   14397                 :          0 :                 flow_dv_translate_item_vxlan(dev, wks->attr, key,
   14398                 :            :                                              items, tunnel, wks, key_type);
   14399         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14400                 :            :                 last_item = MLX5_FLOW_LAYER_VXLAN;
   14401                 :          0 :                 break;
   14402                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
   14403         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14404                 :          0 :                 wks->tunnel_item = items;
   14405                 :            :                 last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
   14406                 :          0 :                 break;
   14407                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE:
   14408         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14409                 :          0 :                 wks->tunnel_item = items;
   14410                 :            :                 last_item = MLX5_FLOW_LAYER_GENEVE;
   14411                 :          0 :                 break;
   14412                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
   14413                 :          0 :                 ret = flow_dv_translate_item_geneve_opt
   14414                 :            :                                 (dev, key, items, key_type, error);
   14415         [ #  # ]:          0 :                 if (ret)
   14416                 :          0 :                         return rte_flow_error_set(error, -ret,
   14417                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14418                 :            :                                 "cannot create GENEVE TLV option");
   14419                 :          0 :                 wks->geneve_tlv_option = 1;
   14420                 :            :                 last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
   14421                 :          0 :                 break;
   14422                 :          0 :         case RTE_FLOW_ITEM_TYPE_MPLS:
   14423                 :          0 :                 flow_dv_translate_item_mpls(key, items, last_item,
   14424                 :            :                                             tunnel, key_type);
   14425         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14426                 :            :                 last_item = MLX5_FLOW_LAYER_MPLS;
   14427                 :          0 :                 break;
   14428                 :          0 :         case RTE_FLOW_ITEM_TYPE_MARK:
   14429                 :          0 :                 flow_dv_translate_item_mark(dev, key, items, key_type);
   14430                 :            :                 last_item = MLX5_FLOW_ITEM_MARK;
   14431                 :          0 :                 break;
   14432                 :          0 :         case RTE_FLOW_ITEM_TYPE_META:
   14433                 :          0 :                 flow_dv_translate_item_meta
   14434                 :            :                                 (dev, key, wks->attr, items, key_type);
   14435                 :            :                 last_item = MLX5_FLOW_ITEM_METADATA;
   14436                 :          0 :                 break;
   14437                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP:
   14438                 :          0 :                 flow_dv_translate_item_icmp(key, items, tunnel, key_type);
   14439                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14440                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP;
   14441                 :          0 :                 break;
   14442                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP6:
   14443                 :          0 :                 flow_dv_translate_item_icmp6(key, items, tunnel, key_type);
   14444                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14445                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP6;
   14446                 :          0 :                 break;
   14447                 :          0 :         case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
   14448                 :            :         case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
   14449                 :          0 :                 flow_dv_translate_item_icmp6_echo(key, items, tunnel, key_type);
   14450                 :          0 :                 wks->priority = MLX5_PRIORITY_MAP_L4;
   14451                 :            :                 last_item = MLX5_FLOW_LAYER_ICMP6;
   14452                 :          0 :                 break;
   14453                 :          0 :         case RTE_FLOW_ITEM_TYPE_TAG:
   14454                 :          0 :                 ret = flow_dv_translate_item_tag(dev, key, items, key_type);
   14455         [ #  # ]:          0 :                 if (ret < 0)
   14456                 :          0 :                         return rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14457                 :            :                                                   "invalid flow tag item");
   14458                 :            :                 last_item = MLX5_FLOW_ITEM_TAG;
   14459                 :            :                 break;
   14460                 :          0 :         case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
   14461                 :          0 :                 flow_dv_translate_mlx5_item_tag(dev, key, items, key_type);
   14462                 :            :                 last_item = MLX5_FLOW_ITEM_TAG;
   14463                 :          0 :                 break;
   14464                 :          0 :         case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
   14465                 :          0 :                 ret = flow_dv_translate_item_tx_queue(dev, key, items, key_type);
   14466         [ #  # ]:          0 :                 if (ret)
   14467                 :          0 :                         return rte_flow_error_set(error, -ret,
   14468                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14469                 :            :                                 "invalid tx_queue item");
   14470                 :            :                 last_item = MLX5_FLOW_ITEM_SQ;
   14471                 :            :                 break;
   14472                 :          0 :         case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   14473                 :          0 :                 flow_dv_translate_item_sq(key, items, key_type);
   14474                 :            :                 last_item = MLX5_FLOW_ITEM_SQ;
   14475                 :          0 :                 break;
   14476                 :          0 :         case RTE_FLOW_ITEM_TYPE_GTP:
   14477                 :          0 :                 flow_dv_translate_item_gtp(key, items, tunnel, key_type);
   14478         [ #  # ]:          0 :                 wks->priority = MLX5_TUNNEL_PRIO_GET(rss_desc);
   14479                 :            :                 last_item = MLX5_FLOW_LAYER_GTP;
   14480                 :          0 :                 break;
   14481                 :          0 :         case RTE_FLOW_ITEM_TYPE_GTP_PSC:
   14482                 :          0 :                 ret = flow_dv_translate_item_gtp_psc(key, items, key_type);
   14483         [ #  # ]:          0 :                 if (ret)
   14484                 :          0 :                         return rte_flow_error_set(error, -ret,
   14485                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14486                 :            :                                 "cannot create GTP PSC item");
   14487                 :            :                 last_item = MLX5_FLOW_LAYER_GTP_PSC;
   14488                 :            :                 break;
   14489                 :          0 :         case RTE_FLOW_ITEM_TYPE_ECPRI:
   14490         [ #  # ]:          0 :                 if (!mlx5_flex_parser_ecpri_exist(dev)) {
   14491                 :            :                         /* Create it only the first time to be used. */
   14492                 :          0 :                         ret = mlx5_flex_parser_ecpri_alloc(dev);
   14493         [ #  # ]:          0 :                         if (ret)
   14494                 :          0 :                                 return rte_flow_error_set
   14495                 :            :                                         (error, -ret,
   14496                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM,
   14497                 :            :                                         NULL,
   14498                 :            :                                         "cannot create eCPRI parser");
   14499                 :            :                 }
   14500                 :          0 :                 flow_dv_translate_item_ecpri
   14501                 :            :                                 (dev, key, items, last_item, key_type);
   14502                 :            :                 /* No other protocol should follow eCPRI layer. */
   14503                 :            :                 last_item = MLX5_FLOW_LAYER_ECPRI;
   14504                 :          0 :                 break;
   14505                 :          0 :         case RTE_FLOW_ITEM_TYPE_METER_COLOR:
   14506                 :          0 :                 flow_dv_translate_item_meter_color(dev, key, items, key_type);
   14507                 :            :                 last_item = MLX5_FLOW_ITEM_METER_COLOR;
   14508                 :          0 :                 break;
   14509         [ #  # ]:          0 :         case RTE_FLOW_ITEM_TYPE_INTEGRITY:
   14510                 :            :                 last_item = flow_dv_translate_item_integrity(items,
   14511                 :            :                                                              wks, key_type);
   14512                 :          0 :                 break;
   14513                 :          0 :         case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
   14514                 :          0 :                 flow_dv_translate_item_aggr_affinity(key, items, key_type);
   14515                 :            :                 last_item = MLX5_FLOW_ITEM_AGGR_AFFINITY;
   14516                 :          0 :                 break;
   14517                 :          0 :         case RTE_FLOW_ITEM_TYPE_IB_BTH:
   14518                 :          0 :                 flow_dv_translate_item_ib_bth(key, items, tunnel, key_type);
   14519                 :            :                 last_item = MLX5_FLOW_ITEM_IB_BTH;
   14520                 :          0 :                 break;
   14521                 :          0 :         case RTE_FLOW_ITEM_TYPE_NSH:
   14522                 :            :                 last_item = MLX5_FLOW_ITEM_NSH;
   14523                 :          0 :                 break;
   14524                 :            :         default:
   14525                 :            :                 break;
   14526                 :            :         }
   14527                 :          0 :         wks->item_flags |= last_item;
   14528                 :          0 :         wks->last_item = last_item;
   14529                 :          0 :         wks->next_protocol = next_protocol;
   14530                 :          0 :         return 0;
   14531                 :            : }
   14532                 :            : 
   14533                 :            : static int
   14534                 :          0 : flow_dv_translate_items_geneve_opt_nta(struct rte_eth_dev *dev,
   14535                 :            :                                    const struct rte_flow_item *items,
   14536                 :            :                                    struct mlx5_flow_attr *attr,
   14537                 :            :                                    struct rte_flow_error *error)
   14538                 :            : {
   14539                 :          0 :         rte_be32_t geneve_mask = 0xffffffff;
   14540                 :          0 :         struct rte_pmd_mlx5_geneve_tlv geneve_tlv = {
   14541                 :            :                 /* Take from item spec, if changed, destroy and add new parser. */
   14542                 :            :                 .option_class                   = 0,
   14543                 :            :                 /* Take from item spec, if changed, destroy and add new parser. */
   14544                 :            :                 .option_type                    = 0,
   14545                 :            :                 /* 1DW is supported. */
   14546                 :            :                 .option_len                     = 1,
   14547                 :            :                 .match_on_class_mode            = 1,
   14548                 :            :                 .offset                         = 0,
   14549                 :            :                 .sample_len                     = 1,
   14550                 :            :                 .match_data_mask                = &geneve_mask
   14551                 :            :         };
   14552                 :          0 :         const struct rte_flow_item_geneve_opt *geneve_opt_v = items->spec;
   14553                 :          0 :         const struct rte_flow_item_geneve_opt *geneve_opt_m = items->mask;
   14554                 :            :         void *geneve_parser;
   14555                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14556                 :            : #ifdef RTE_PMD_MLX5_DEBUG
   14557                 :            :         struct mlx5_geneve_tlv_option *option;
   14558                 :            : #endif
   14559                 :            : 
   14560                 :            :         /* option length is not as supported. */
   14561         [ #  # ]:          0 :         if ((geneve_opt_v->option_len & geneve_opt_m->option_len) > geneve_tlv.option_len)
   14562                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   14563                 :            :                         RTE_FLOW_ERROR_TYPE_ITEM, items,
   14564                 :            :                         " GENEVE OPT length is not supported ");
   14565                 :          0 :         geneve_tlv.option_class = geneve_opt_v->option_class & geneve_opt_m->option_class;
   14566                 :          0 :         geneve_tlv.option_type = geneve_opt_v->option_type & geneve_opt_m->option_type;
   14567                 :            :         /* if parser doesn't exist */
   14568         [ #  # ]:          0 :         if (!priv->tlv_options) {
   14569                 :            :                 /* Create a GENEVE option parser. */
   14570                 :          0 :                 geneve_parser = mlx5_geneve_tlv_parser_create(attr->port_id,
   14571                 :            :                                                 &geneve_tlv, 1);
   14572         [ #  # ]:          0 :                 if (!geneve_parser)
   14573                 :          0 :                         return rte_flow_error_set(error, EINVAL,
   14574                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, items,
   14575                 :            :                                 " GENEVE OPT parser creation failed ");
   14576                 :            : #ifdef RTE_PMD_MLX5_DEBUG
   14577                 :            :         } else {
   14578                 :            :                 /* Check if option exist in current parser. */
   14579                 :            :                 option = mlx5_geneve_tlv_option_get(priv,
   14580                 :            :                                                 geneve_tlv.option_type,
   14581                 :            :                                                 geneve_tlv.option_class);
   14582                 :            :                 if (!option)
   14583                 :            :                         return rte_flow_error_set(error, EINVAL,
   14584                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, items,
   14585                 :            :                                 " GENEVE OPT configured does not match this rule class/type");
   14586                 :            : #endif
   14587                 :            :         }
   14588                 :            :         return 0;
   14589                 :            : }
   14590                 :            : 
   14591                 :            : /**
   14592                 :            :  * Fill the flow matcher with DV spec for items supported in non template mode.
   14593                 :            :  *
   14594                 :            :  * @param[in] dev
   14595                 :            :  *   Pointer to rte_eth_dev structure.
   14596                 :            :  * @param[in] items
   14597                 :            :  *   Pointer to the list of items.
   14598                 :            :  * @param[in] wks
   14599                 :            :  *   Pointer to the matcher workspace.
   14600                 :            :  * @param[in] key
   14601                 :            :  *   Pointer to the flow matcher key.
   14602                 :            :  * @param[in] key_type
   14603                 :            :  *   Key type.
   14604                 :            :  * @param[out] error
   14605                 :            :  *   Pointer to the error structure.
   14606                 :            :  *
   14607                 :            :  * @return
   14608                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14609                 :            :  */
   14610                 :            : static int
   14611                 :          0 : flow_dv_translate_items_nta(struct rte_eth_dev *dev,
   14612                 :            :                         const struct rte_flow_item *items,
   14613                 :            :                         struct mlx5_dv_matcher_workspace *wks,
   14614                 :            :                         void *key, uint32_t key_type,
   14615                 :            :                         struct mlx5_flow_attr *attr,
   14616                 :            :                         struct rte_flow_error *error)
   14617                 :            : {
   14618                 :            :         int item_type;
   14619                 :            :         int ret = 0;
   14620                 :            :         int tunnel;
   14621                 :            :         /* Dummy structure to enable the key calculation for flex item. */
   14622                 :            :         struct mlx5_flow_dv_match_params flex_item_key;
   14623                 :            : 
   14624                 :          0 :         tunnel = !!(wks->item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14625                 :          0 :         item_type = items->type;
   14626   [ #  #  #  # ]:          0 :         switch (item_type) {
   14627                 :          0 :         case RTE_FLOW_ITEM_TYPE_CONNTRACK:
   14628                 :          0 :                 flow_dv_translate_item_aso_ct(dev, key, NULL, items);
   14629                 :          0 :                 wks->last_item = MLX5_FLOW_LAYER_ASO_CT;
   14630                 :          0 :                 break;
   14631                 :            :         /* TODO: remove once flex item translation is added to flow_dv_translate_items. */
   14632                 :          0 :         case RTE_FLOW_ITEM_TYPE_FLEX:
   14633                 :          0 :                 mlx5_flex_flow_translate_item(dev, key, flex_item_key.buf, items, tunnel != 0);
   14634         [ #  # ]:          0 :                 wks->last_item = tunnel ? MLX5_FLOW_ITEM_INNER_FLEX : MLX5_FLOW_ITEM_OUTER_FLEX;
   14635                 :          0 :                 break;
   14636                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
   14637                 :          0 :                 ret = flow_dv_translate_items_geneve_opt_nta(dev, items, attr, error);
   14638         [ #  # ]:          0 :                 if (ret)
   14639                 :            :                         return ret;
   14640                 :          0 :                 wks->last_item = MLX5_FLOW_LAYER_GENEVE_OPT;
   14641                 :          0 :                 break;
   14642                 :          0 :         default:
   14643                 :          0 :                 ret = flow_dv_translate_items(dev, items, wks, key, key_type,  error);
   14644         [ #  # ]:          0 :                 if (ret)
   14645                 :            :                         return ret;
   14646                 :            :                 break;
   14647                 :            :         }
   14648                 :          0 :         wks->item_flags |= wks->last_item;
   14649                 :          0 :         return 0;
   14650                 :            : }
   14651                 :            : 
   14652                 :            : /**
   14653                 :            :  * Fill the HW steering flow with DV spec.
   14654                 :            :  *
   14655                 :            :  * @param[in] items
   14656                 :            :  *   Pointer to the list of items.
   14657                 :            :  * @param[in] attr
   14658                 :            :  *   Pointer to the flow attributes.
   14659                 :            :  * @param[in] key
   14660                 :            :  *   Pointer to the flow matcher key.
   14661                 :            :  * @param[in] key_type
   14662                 :            :  *   Key type.
   14663                 :            :  * @param[in, out] item_flags
   14664                 :            :  *   Pointer to the flow item flags.
   14665                 :            :  * @param[in, out] nt_flow
   14666                 :            :  *   Non template flow.
   14667                 :            :  * @param[out] error
   14668                 :            :  *   Pointer to the error structure.
   14669                 :            :  *
   14670                 :            :  * @return
   14671                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14672                 :            :  */
   14673                 :            : int
   14674                 :          0 : mlx5_flow_dv_translate_items_hws_impl(const struct rte_flow_item *items,
   14675                 :            :                                       struct mlx5_flow_attr *attr, void *key,
   14676                 :            :                                       uint32_t key_type, uint64_t *item_flags,
   14677                 :            :                                       uint8_t *match_criteria,
   14678                 :            :                                       bool nt_flow,
   14679                 :            :                                       struct rte_flow_error *error)
   14680                 :            : {
   14681                 :          0 :         struct mlx5_flow_workspace *flow_wks = mlx5_flow_push_thread_workspace();
   14682                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { .level = attr->rss_level };
   14683                 :          0 :         struct rte_flow_attr rattr = {
   14684                 :          0 :                 .group = attr->group,
   14685                 :          0 :                 .priority = attr->priority,
   14686                 :          0 :                 .ingress = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_NIC_RX),
   14687                 :          0 :                 .egress = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_NIC_TX),
   14688                 :          0 :                 .transfer = !!(attr->tbl_type == MLX5DR_TABLE_TYPE_FDB),
   14689                 :            :         };
   14690                 :          0 :         struct mlx5_dv_matcher_workspace wks = {
   14691                 :          0 :                 .action_flags = attr->act_flags,
   14692         [ #  # ]:          0 :                 .item_flags = item_flags ? *item_flags : 0,
   14693                 :            :                 .external = 0,
   14694                 :            :                 .next_protocol = 0xff,
   14695                 :            :                 .attr = &rattr,
   14696                 :            :                 .rss_desc = &rss_desc,
   14697                 :            :                 .group = attr->group,
   14698                 :            :         };
   14699                 :            :         int ret = 0;
   14700                 :            : 
   14701                 :            :         RTE_SET_USED(flow_wks);
   14702         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
   14703                 :            :                 if (!mlx5_flow_os_item_supported(items->type)) {
   14704                 :            :                         ret = rte_flow_error_set(error, ENOTSUP,
   14705                 :            :                                                  RTE_FLOW_ERROR_TYPE_ITEM,
   14706                 :            :                                                  NULL, "item not supported");
   14707                 :            :                         goto exit;
   14708                 :            :                 }
   14709                 :            :                 /* Non template flow. */
   14710         [ #  # ]:          0 :                 if (nt_flow) {
   14711                 :          0 :                         ret = flow_dv_translate_items_nta(&rte_eth_devices[attr->port_id],
   14712                 :            :                                                           items, &wks, key, key_type, attr, error);
   14713         [ #  # ]:          0 :                         if (ret)
   14714                 :          0 :                                 goto exit;
   14715                 :            :                 } else {
   14716                 :          0 :                         ret = flow_dv_translate_items(&rte_eth_devices[attr->port_id],
   14717                 :            :                                                       items, &wks, key, key_type, error);
   14718         [ #  # ]:          0 :                         if (ret)
   14719                 :          0 :                                 goto exit;
   14720                 :            :                 }
   14721                 :            :         }
   14722         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
   14723                 :          0 :                 flow_dv_translate_item_integrity_post(key,
   14724                 :            :                                                       wks.integrity_items,
   14725                 :            :                                                       wks.item_flags,
   14726                 :            :                                                       key_type);
   14727                 :            :         }
   14728         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_LAYER_VXLAN_GPE) {
   14729         [ #  # ]:          0 :                 if (wks.tunnel_item)
   14730                 :          0 :                         flow_dv_translate_item_vxlan_gpe(key,
   14731                 :            :                                                          wks.tunnel_item,
   14732                 :            :                                                          wks.item_flags,
   14733                 :            :                                                          key_type);
   14734         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GENEVE) {
   14735         [ #  # ]:          0 :                 if (wks.tunnel_item)
   14736                 :          0 :                         flow_dv_translate_item_geneve(key,
   14737                 :            :                                                       wks.tunnel_item,
   14738                 :            :                                                       wks.item_flags,
   14739                 :            :                                                       key_type);
   14740         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GRE) {
   14741   [ #  #  #  # ]:          0 :                 if (wks.tunnel_item && wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE) {
   14742                 :          0 :                         flow_dv_translate_item_gre(key,
   14743                 :            :                                                    wks.tunnel_item,
   14744                 :            :                                                    wks.item_flags,
   14745                 :            :                                                    key_type);
   14746         [ #  # ]:          0 :                 } else if (wks.tunnel_item &&
   14747         [ #  # ]:          0 :                            wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION) {
   14748                 :          0 :                         flow_dv_translate_item_gre_option(key,
   14749                 :            :                                                           wks.tunnel_item,
   14750                 :            :                                                           wks.gre_item,
   14751                 :            :                                                           wks.item_flags,
   14752                 :            :                                                           key_type);
   14753   [ #  #  #  # ]:          0 :                 } else if (wks.tunnel_item && wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
   14754                 :          0 :                         flow_dv_translate_item_nvgre(key,
   14755                 :            :                                                      wks.tunnel_item,
   14756                 :            :                                                      wks.item_flags,
   14757                 :            :                                                      key_type);
   14758                 :            :                 } else {
   14759                 :            :                         MLX5_ASSERT(false);
   14760                 :            :                 }
   14761                 :            :         }
   14762                 :            : 
   14763         [ #  # ]:          0 :         if (match_criteria)
   14764                 :          0 :                 *match_criteria = flow_dv_matcher_enable(key);
   14765         [ #  # ]:          0 :         if (item_flags)
   14766                 :          0 :                 *item_flags = wks.item_flags;
   14767                 :          0 : exit:
   14768                 :          0 :         mlx5_flow_pop_thread_workspace();
   14769                 :          0 :         return ret;
   14770                 :            : }
   14771                 :            : 
   14772                 :            : /**
   14773                 :            :  * Fill the HW steering flow with DV spec.
   14774                 :            :  * This function assumes given flow is created from template API.
   14775                 :            :  *
   14776                 :            :  * @param[in] items
   14777                 :            :  *   Pointer to the list of items.
   14778                 :            :  * @param[in] attr
   14779                 :            :  *   Pointer to the flow attributes.
   14780                 :            :  * @param[in] key
   14781                 :            :  *   Pointer to the flow matcher key.
   14782                 :            :  * @param[in] key_type
   14783                 :            :  *   Key type.
   14784                 :            :  * @param[in, out] item_flags
   14785                 :            :  *   Pointer to the flow item flags.
   14786                 :            :  * @param[out] error
   14787                 :            :  *   Pointer to the error structure.
   14788                 :            :  *
   14789                 :            :  * @return
   14790                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14791                 :            :  */
   14792                 :            : int
   14793                 :          0 : mlx5_flow_dv_translate_items_hws(const struct rte_flow_item *items,
   14794                 :            :                                  struct mlx5_flow_attr *attr, void *key,
   14795                 :            :                                  uint32_t key_type, uint64_t *item_flags,
   14796                 :            :                                  uint8_t *match_criteria,
   14797                 :            :                                  struct rte_flow_error *error)
   14798                 :            : {
   14799                 :          0 :         return mlx5_flow_dv_translate_items_hws_impl(items, attr, key, key_type, item_flags,
   14800                 :            :                                                      match_criteria, false, error);
   14801                 :            : }
   14802                 :            : 
   14803                 :            : /**
   14804                 :            :  * Fill the SW steering flow with DV spec.
   14805                 :            :  *
   14806                 :            :  * @param[in] dev
   14807                 :            :  *   Pointer to rte_eth_dev structure.
   14808                 :            :  * @param[in, out] dev_flow
   14809                 :            :  *   Pointer to the sub flow.
   14810                 :            :  * @param[in] attr
   14811                 :            :  *   Pointer to the flow attributes.
   14812                 :            :  * @param[in] items
   14813                 :            :  *   Pointer to the list of items.
   14814                 :            :  * @param[in, out] matcher
   14815                 :            :  *   Pointer to the flow matcher.
   14816                 :            :  * @param[out] error
   14817                 :            :  *   Pointer to the error structure.
   14818                 :            :  *
   14819                 :            :  * @return
   14820                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   14821                 :            :  */
   14822                 :            : static int
   14823                 :          0 : flow_dv_translate_items_sws(struct rte_eth_dev *dev,
   14824                 :            :                             struct mlx5_flow *dev_flow,
   14825                 :            :                             const struct rte_flow_attr *attr,
   14826                 :            :                             const struct rte_flow_item *items,
   14827                 :            :                             struct mlx5_flow_dv_matcher *matcher,
   14828                 :            :                             struct rte_flow_error *error)
   14829                 :            : {
   14830                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   14831                 :          0 :         void *match_mask = matcher->mask.buf;
   14832                 :          0 :         void *match_value = dev_flow->dv.value.buf;
   14833                 :          0 :         struct mlx5_dv_matcher_workspace wks = {
   14834                 :          0 :                 .action_flags = dev_flow->act_flags,
   14835                 :            :                 .item_flags = 0,
   14836                 :          0 :                 .external = dev_flow->external,
   14837                 :            :                 .next_protocol = 0xff,
   14838                 :          0 :                 .group = dev_flow->dv.group,
   14839                 :            :                 .attr = attr,
   14840                 :          0 :                 .rss_desc = &((struct mlx5_flow_workspace *)
   14841                 :            :                              mlx5_flow_get_thread_workspace())->rss_desc,
   14842                 :            :         };
   14843                 :          0 :         struct mlx5_dv_matcher_workspace wks_m = wks;
   14844                 :            :         int item_type;
   14845                 :            :         int ret = 0;
   14846                 :            :         int tunnel;
   14847                 :            : 
   14848         [ #  # ]:          0 :         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
   14849                 :          0 :                 if (!mlx5_flow_os_item_supported(items->type))
   14850                 :            :                         return rte_flow_error_set(error, ENOTSUP,
   14851                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
   14852                 :            :                                                   NULL, "item not supported");
   14853                 :          0 :                 tunnel = !!(wks.item_flags & MLX5_FLOW_LAYER_TUNNEL);
   14854                 :            :                 item_type = items->type;
   14855   [ #  #  #  #  :          0 :                 switch (item_type) {
                      # ]
   14856                 :          0 :                 case RTE_FLOW_ITEM_TYPE_CONNTRACK:
   14857                 :          0 :                         flow_dv_translate_item_aso_ct(dev, match_mask,
   14858                 :            :                                                       match_value, items);
   14859                 :          0 :                         wks.last_item = MLX5_FLOW_LAYER_ASO_CT;
   14860                 :          0 :                         break;
   14861                 :          0 :                 case RTE_FLOW_ITEM_TYPE_FLEX:
   14862                 :          0 :                         flow_dv_translate_item_flex(dev, match_mask,
   14863                 :            :                                                     match_value, items,
   14864                 :            :                                                     dev_flow, tunnel != 0);
   14865         [ #  # ]:          0 :                         wks.last_item = tunnel ? MLX5_FLOW_ITEM_INNER_FLEX :
   14866                 :            :                                                  MLX5_FLOW_ITEM_OUTER_FLEX;
   14867                 :          0 :                         break;
   14868                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
   14869                 :          0 :                         ret = flow_dv_translate_item_tx_queue(dev, match_value, items,
   14870                 :            :                                                               MLX5_SET_MATCHER_SW_V);
   14871         [ #  # ]:          0 :                         if (ret)
   14872                 :          0 :                                 return rte_flow_error_set(error, -ret,
   14873                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14874                 :            :                                         "invalid tx_queue item spec");
   14875                 :          0 :                         ret = flow_dv_translate_item_tx_queue(dev, match_mask, items,
   14876                 :            :                                                               MLX5_SET_MATCHER_SW_M);
   14877         [ #  # ]:          0 :                         if (ret)
   14878                 :          0 :                                 return rte_flow_error_set(error, -ret,
   14879                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
   14880                 :            :                                         "invalid tx_queue item mask");
   14881                 :            :                         break;
   14882                 :          0 :                 case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
   14883                 :          0 :                         flow_dv_translate_item_sq(match_value, items,
   14884                 :            :                                                   MLX5_SET_MATCHER_SW_V);
   14885                 :          0 :                         flow_dv_translate_item_sq(match_mask, items,
   14886                 :            :                                                   MLX5_SET_MATCHER_SW_M);
   14887                 :          0 :                         break;
   14888                 :          0 :                 default:
   14889                 :          0 :                         ret = flow_dv_translate_items(dev, items, &wks_m,
   14890                 :            :                                 match_mask, MLX5_SET_MATCHER_SW_M, error);
   14891         [ #  # ]:          0 :                         if (ret)
   14892                 :          0 :                                 return ret;
   14893                 :          0 :                         ret = flow_dv_translate_items(dev, items, &wks,
   14894                 :            :                                 match_value, MLX5_SET_MATCHER_SW_V, error);
   14895         [ #  # ]:          0 :                         if (ret)
   14896                 :          0 :                                 return ret;
   14897                 :            :                         break;
   14898                 :            :                 }
   14899                 :          0 :                 wks.item_flags |= wks.last_item;
   14900                 :            :         }
   14901                 :            :         /*
   14902                 :            :          * When E-Switch mode is enabled, we have two cases where we need to
   14903                 :            :          * set the source port manually.
   14904                 :            :          * The first one, is in case of NIC ingress steering rule, and the
   14905                 :            :          * second is E-Switch rule where no port_id item was found.
   14906                 :            :          * In both cases the source port is set according the current port
   14907                 :            :          * in use.
   14908                 :            :          */
   14909                 :          0 :         if (!(wks.item_flags & MLX5_FLOW_ITEM_PORT_ID) &&
   14910         [ #  # ]:          0 :             !(wks.item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT) &&
   14911                 :          0 :             !(wks.item_flags & MLX5_FLOW_ITEM_PORT_REPRESENTOR) &&
   14912         [ #  # ]:          0 :             priv->sh->esw_mode &&
   14913         [ #  # ]:          0 :             !attr->egress &&
   14914         [ #  # ]:          0 :             attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP) {
   14915         [ #  # ]:          0 :                 if (flow_dv_translate_item_port_id_all(dev, match_mask,
   14916                 :            :                                                    match_value, NULL, attr))
   14917                 :          0 :                         return -rte_errno;
   14918                 :            :         }
   14919         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_ITEM_INTEGRITY) {
   14920                 :          0 :                 flow_dv_translate_item_integrity_post(match_mask,
   14921                 :            :                                                       wks_m.integrity_items,
   14922                 :            :                                                       wks_m.item_flags,
   14923                 :            :                                                       MLX5_SET_MATCHER_SW_M);
   14924                 :          0 :                 flow_dv_translate_item_integrity_post(match_value,
   14925                 :            :                                                       wks.integrity_items,
   14926                 :            :                                                       wks.item_flags,
   14927                 :            :                                                       MLX5_SET_MATCHER_SW_V);
   14928                 :            :         }
   14929         [ #  # ]:          0 :         if (wks.item_flags & MLX5_FLOW_LAYER_VXLAN_GPE) {
   14930                 :          0 :                 flow_dv_translate_item_vxlan_gpe(match_mask,
   14931                 :            :                                                  wks.tunnel_item,
   14932                 :            :                                                  wks.item_flags,
   14933                 :            :                                                  MLX5_SET_MATCHER_SW_M);
   14934                 :          0 :                 flow_dv_translate_item_vxlan_gpe(match_value,
   14935                 :            :                                                  wks.tunnel_item,
   14936                 :            :                                                  wks.item_flags,
   14937                 :            :                                                  MLX5_SET_MATCHER_SW_V);
   14938         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GENEVE) {
   14939                 :          0 :                 flow_dv_translate_item_geneve(match_mask,
   14940                 :            :                                               wks.tunnel_item,
   14941                 :            :                                               wks.item_flags,
   14942                 :            :                                               MLX5_SET_MATCHER_SW_M);
   14943                 :          0 :                 flow_dv_translate_item_geneve(match_value,
   14944                 :            :                                               wks.tunnel_item,
   14945                 :            :                                               wks.item_flags,
   14946                 :            :                                               MLX5_SET_MATCHER_SW_V);
   14947         [ #  # ]:          0 :         } else if (wks.item_flags & MLX5_FLOW_LAYER_GRE) {
   14948         [ #  # ]:          0 :                 if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE) {
   14949                 :          0 :                         flow_dv_translate_item_gre(match_mask,
   14950                 :            :                                                    wks.tunnel_item,
   14951                 :            :                                                    wks.item_flags,
   14952                 :            :                                                    MLX5_SET_MATCHER_SW_M);
   14953                 :          0 :                         flow_dv_translate_item_gre(match_value,
   14954                 :            :                                                    wks.tunnel_item,
   14955                 :            :                                                    wks.item_flags,
   14956                 :            :                                                    MLX5_SET_MATCHER_SW_V);
   14957         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
   14958                 :          0 :                         flow_dv_translate_item_nvgre(match_mask,
   14959                 :            :                                                      wks.tunnel_item,
   14960                 :            :                                                      wks.item_flags,
   14961                 :            :                                                      MLX5_SET_MATCHER_SW_M);
   14962                 :          0 :                         flow_dv_translate_item_nvgre(match_value,
   14963                 :            :                                                      wks.tunnel_item,
   14964                 :            :                                                      wks.item_flags,
   14965                 :            :                                                      MLX5_SET_MATCHER_SW_V);
   14966         [ #  # ]:          0 :                 } else if (wks.tunnel_item->type == RTE_FLOW_ITEM_TYPE_GRE_OPTION) {
   14967                 :          0 :                         flow_dv_translate_item_gre_option(match_mask,
   14968                 :            :                                                           wks.tunnel_item,
   14969                 :            :                                                           wks.gre_item,
   14970                 :            :                                                           wks.item_flags,
   14971                 :            :                                                           MLX5_SET_MATCHER_SW_M);
   14972                 :          0 :                         flow_dv_translate_item_gre_option(match_value,
   14973                 :            :                                                           wks.tunnel_item,
   14974                 :            :                                                           wks.gre_item,
   14975                 :            :                                                           wks.item_flags,
   14976                 :            :                                                           MLX5_SET_MATCHER_SW_V);
   14977                 :            :                 } else {
   14978                 :            :                         MLX5_ASSERT(false);
   14979                 :            :                 }
   14980                 :            :         }
   14981                 :          0 :         dev_flow->handle->vf_vlan.tag = wks.vlan_tag;
   14982                 :          0 :         matcher->priority = wks.priority;
   14983                 :            : #ifdef RTE_PMD_MLX5_DEBUG
   14984                 :            :         MLX5_ASSERT(!flow_dv_check_valid_spec(match_mask, match_value));
   14985                 :            : #endif
   14986                 :            :         /*
   14987                 :            :          * Layers may be already initialized from prefix flow if this dev_flow
   14988                 :            :          * is the suffix flow.
   14989                 :            :          */
   14990                 :          0 :         dev_flow->handle->layers |= wks.item_flags;
   14991                 :            :         /*
   14992                 :            :          * Update geneve_tlv_option flag only it is set in workspace.
   14993                 :            :          * Avoid be overwritten by other sub mlx5_flows.
   14994                 :            :          */
   14995         [ #  # ]:          0 :         if (wks.geneve_tlv_option)
   14996                 :          0 :                 dev_flow->flow->geneve_tlv_option += wks.geneve_tlv_option;
   14997                 :            :         return 0;
   14998                 :            : }
   14999                 :            : 
   15000                 :            : /**
   15001                 :            :  * Fill the flow with DV spec, lock free
   15002                 :            :  * (mutex should be acquired by caller).
   15003                 :            :  *
   15004                 :            :  * @param[in] dev
   15005                 :            :  *   Pointer to rte_eth_dev structure.
   15006                 :            :  * @param[in, out] dev_flow
   15007                 :            :  *   Pointer to the sub flow.
   15008                 :            :  * @param[in] attr
   15009                 :            :  *   Pointer to the flow attributes.
   15010                 :            :  * @param[in] items
   15011                 :            :  *   Pointer to the list of items.
   15012                 :            :  * @param[in] actions
   15013                 :            :  *   Pointer to the list of actions.
   15014                 :            :  * @param[out] error
   15015                 :            :  *   Pointer to the error structure.
   15016                 :            :  *
   15017                 :            :  * @return
   15018                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   15019                 :            :  */
   15020                 :            : static int
   15021                 :          0 : flow_dv_translate(struct rte_eth_dev *dev,
   15022                 :            :                   struct mlx5_flow *dev_flow,
   15023                 :            :                   const struct rte_flow_attr *attr,
   15024                 :            :                   const struct rte_flow_item items[],
   15025                 :            :                   const struct rte_flow_action actions[],
   15026                 :            :                   struct rte_flow_error *error)
   15027                 :            : {
   15028                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   15029                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
   15030                 :          0 :         struct rte_flow *flow = dev_flow->flow;
   15031                 :          0 :         struct mlx5_flow_handle *handle = dev_flow->handle;
   15032                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   15033                 :            :         struct mlx5_flow_rss_desc *rss_desc;
   15034                 :            :         uint64_t action_flags = 0;
   15035                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   15036                 :            :                 .mask = {
   15037                 :            :                         .size = sizeof(matcher.mask.buf),
   15038                 :            :                 },
   15039                 :            :         };
   15040                 :            :         int actions_n = 0;
   15041                 :            :         bool actions_end = false;
   15042                 :            :         union {
   15043                 :            :                 struct mlx5_flow_dv_modify_hdr_resource res;
   15044                 :            :                 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   15045                 :            :                             sizeof(struct mlx5_modification_cmd) *
   15046                 :            :                             (MLX5_MAX_MODIFY_NUM + 1)];
   15047                 :            :         } mhdr_dummy;
   15048                 :            :         struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
   15049                 :            :         const struct rte_flow_action_count *count = NULL;
   15050                 :            :         const struct rte_flow_action_age *non_shared_age = NULL;
   15051                 :          0 :         union flow_dv_attr flow_attr = { .attr = 0 };
   15052                 :            :         uint32_t tag_be;
   15053                 :            :         union mlx5_flow_tbl_key tbl_key;
   15054                 :            :         uint32_t modify_action_position = UINT32_MAX;
   15055                 :          0 :         struct rte_vlan_hdr vlan = { 0 };
   15056                 :            :         struct mlx5_flow_dv_dest_array_resource mdest_res;
   15057                 :            :         struct mlx5_flow_dv_sample_resource sample_res;
   15058                 :          0 :         void *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
   15059                 :            :         const struct rte_flow_action_sample *sample = NULL;
   15060                 :            :         struct mlx5_flow_sub_actions_list *sample_act;
   15061                 :            :         uint32_t sample_act_pos = UINT32_MAX;
   15062                 :            :         uint32_t age_act_pos = UINT32_MAX;
   15063                 :            :         uint32_t ipv6_tc_off = 0;
   15064                 :          0 :         uint32_t num_of_dest = 0;
   15065                 :            :         int tmp_actions_n = 0;
   15066                 :            :         uint32_t table;
   15067                 :            :         int ret = 0;
   15068                 :            :         const struct mlx5_flow_tunnel *tunnel = NULL;
   15069                 :          0 :         struct flow_grp_info grp_info = {
   15070                 :          0 :                 .external = !!dev_flow->external,
   15071                 :          0 :                 .transfer = !!attr->transfer,
   15072                 :          0 :                 .fdb_def_rule = !!priv->fdb_def_rule,
   15073                 :          0 :                 .skip_scale = dev_flow->skip_scale &
   15074                 :            :                         (1 << MLX5_SCALE_FLOW_GROUP_BIT),
   15075                 :            :                 .std_tbl_fix = true,
   15076                 :            :         };
   15077                 :            : 
   15078         [ #  # ]:          0 :         if (!wks)
   15079                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   15080                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15081                 :            :                                           NULL,
   15082                 :            :                                           "failed to push flow workspace");
   15083         [ #  # ]:          0 :         rss_desc = &wks->rss_desc;
   15084                 :            :         memset(&mdest_res, 0, sizeof(struct mlx5_flow_dv_dest_array_resource));
   15085                 :            :         memset(&sample_res, 0, sizeof(struct mlx5_flow_dv_sample_resource));
   15086         [ #  # ]:          0 :         mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   15087                 :            :                                            MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   15088                 :            :         /* update normal path action resource into last index of array */
   15089                 :            :         sample_act = &mdest_res.sample_act[MLX5_MAX_DEST_NUM - 1];
   15090         [ #  # ]:          0 :         if (is_tunnel_offload_active(dev)) {
   15091         [ #  # ]:          0 :                 if (dev_flow->tunnel) {
   15092         [ #  # ]:          0 :                         RTE_VERIFY(dev_flow->tof_type ==
   15093                 :            :                                    MLX5_TUNNEL_OFFLOAD_MISS_RULE);
   15094                 :            :                         tunnel = dev_flow->tunnel;
   15095                 :            :                 } else {
   15096                 :          0 :                         tunnel = mlx5_get_tof(items, actions,
   15097                 :            :                                               &dev_flow->tof_type);
   15098                 :          0 :                         dev_flow->tunnel = tunnel;
   15099                 :            :                 }
   15100         [ #  # ]:          0 :                 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
   15101                 :            :                                         (dev, attr, tunnel, dev_flow->tof_type);
   15102                 :            :         }
   15103                 :          0 :         mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   15104                 :            :                                            MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
   15105                 :          0 :         ret = mlx5_flow_group_to_table(dev, tunnel, attr->group, &table,
   15106                 :            :                                        &grp_info, error);
   15107         [ #  # ]:          0 :         if (ret)
   15108                 :            :                 return ret;
   15109                 :          0 :         dev_flow->dv.group = table;
   15110         [ #  # ]:          0 :         if (attr->transfer)
   15111                 :          0 :                 mhdr_res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
   15112                 :            :         /* number of actions must be set to 0 in case of dirty stack. */
   15113                 :          0 :         mhdr_res->actions_num = 0;
   15114         [ #  # ]:          0 :         if (is_flow_tunnel_match_rule(dev_flow->tof_type)) {
   15115                 :            :                 /*
   15116                 :            :                  * do not add decap action if match rule drops packet
   15117                 :            :                  * HW rejects rules with decap & drop
   15118                 :            :                  *
   15119                 :            :                  * if tunnel match rule was inserted before matching tunnel set
   15120                 :            :                  * rule flow table used in the match rule must be registered.
   15121                 :            :                  * current implementation handles that in the
   15122                 :            :                  * flow_dv_match_register() at the function end.
   15123                 :            :                  */
   15124                 :            :                 bool add_decap = true;
   15125                 :            :                 const struct rte_flow_action *ptr = actions;
   15126                 :            : 
   15127         [ #  # ]:          0 :                 for (; ptr->type != RTE_FLOW_ACTION_TYPE_END; ptr++) {
   15128         [ #  # ]:          0 :                         if (ptr->type == RTE_FLOW_ACTION_TYPE_DROP) {
   15129                 :            :                                 add_decap = false;
   15130                 :            :                                 break;
   15131                 :            :                         }
   15132                 :            :                 }
   15133         [ #  # ]:          0 :                 if (add_decap) {
   15134         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_decap(dev, dev_flow,
   15135                 :          0 :                                                            attr->transfer,
   15136                 :            :                                                            error))
   15137                 :          0 :                                 return -rte_errno;
   15138                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15139                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15140                 :            :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   15141                 :            :                 }
   15142                 :            :         }
   15143         [ #  # ]:          0 :         for (; !actions_end ; actions++) {
   15144                 :            :                 const struct rte_flow_action_queue *queue;
   15145                 :            :                 const struct rte_flow_action_rss *rss;
   15146                 :            :                 const struct rte_flow_action *action = actions;
   15147                 :            :                 const uint8_t *rss_key;
   15148                 :            :                 struct mlx5_flow_tbl_resource *tbl;
   15149                 :            :                 struct mlx5_aso_age_action *age_act;
   15150                 :            :                 struct mlx5_flow_counter *cnt_act;
   15151                 :          0 :                 uint32_t port_id = 0;
   15152                 :            :                 struct mlx5_flow_dv_port_id_action_resource port_id_resource;
   15153                 :          0 :                 int action_type = actions->type;
   15154                 :            :                 const struct rte_flow_action *found_action = NULL;
   15155                 :            :                 uint32_t jump_group = 0;
   15156                 :            :                 uint32_t owner_idx;
   15157                 :            :                 struct mlx5_aso_ct_action *ct;
   15158                 :            : 
   15159                 :            :                 if (!mlx5_flow_os_action_supported(action_type))
   15160                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   15161                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   15162                 :            :                                                   actions,
   15163                 :            :                                                   "action not supported");
   15164   [ #  #  #  #  :          0 :                 switch (action_type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
   15165                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET:
   15166                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;
   15167                 :          0 :                         break;
   15168                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   15169                 :            :                         break;
   15170                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PORT_ID:
   15171                 :            :                 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   15172         [ #  # ]:          0 :                         if (flow_dv_translate_action_port_id(dev, action,
   15173                 :            :                                                              &port_id, error))
   15174                 :          0 :                                 return -rte_errno;
   15175                 :          0 :                         port_id_resource.port_id = port_id;
   15176                 :            :                         MLX5_ASSERT(!handle->rix_port_id_action);
   15177         [ #  # ]:          0 :                         if (flow_dv_port_id_action_resource_register
   15178                 :            :                             (dev, &port_id_resource, dev_flow, error))
   15179                 :          0 :                                 return -rte_errno;
   15180                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15181                 :          0 :                                         dev_flow->dv.port_id_action->action;
   15182                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   15183                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_PORT_ID;
   15184                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   15185                 :          0 :                         num_of_dest++;
   15186                 :          0 :                         break;
   15187                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
   15188                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_FLAG;
   15189                 :          0 :                         wks->mark = 1;
   15190         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
   15191                 :          0 :                                 struct rte_flow_action_mark mark = {
   15192                 :            :                                         .id = MLX5_FLOW_MARK_DEFAULT,
   15193                 :            :                                 };
   15194                 :            : 
   15195         [ #  # ]:          0 :                                 if (flow_dv_convert_action_mark(dev, &mark,
   15196                 :            :                                                                 mhdr_res,
   15197                 :            :                                                                 error))
   15198                 :          0 :                                         return -rte_errno;
   15199                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
   15200                 :          0 :                                 break;
   15201                 :            :                         }
   15202                 :            :                         tag_be = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT);
   15203                 :            :                         /*
   15204                 :            :                          * Only one FLAG or MARK is supported per device flow
   15205                 :            :                          * right now. So the pointer to the tag resource must be
   15206                 :            :                          * zero before the register process.
   15207                 :            :                          */
   15208                 :            :                         MLX5_ASSERT(!handle->dvh.rix_tag);
   15209         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   15210                 :            :                                                           dev_flow, error))
   15211                 :          0 :                                 return -rte_errno;
   15212                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   15213                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15214                 :          0 :                                         dev_flow->dv.tag_resource->action;
   15215                 :          0 :                         break;
   15216                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
   15217                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MARK;
   15218                 :          0 :                         wks->mark = 1;
   15219         [ #  # ]:          0 :                         if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
   15220                 :          0 :                                 const struct rte_flow_action_mark *mark =
   15221                 :            :                                         (const struct rte_flow_action_mark *)
   15222                 :            :                                                 actions->conf;
   15223                 :            : 
   15224         [ #  # ]:          0 :                                 if (flow_dv_convert_action_mark(dev, mark,
   15225                 :            :                                                                 mhdr_res,
   15226                 :            :                                                                 error))
   15227                 :          0 :                                         return -rte_errno;
   15228                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
   15229                 :          0 :                                 break;
   15230                 :            :                         }
   15231                 :            :                         /* Fall-through */
   15232                 :            :                 case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
   15233                 :            :                         /* Legacy (non-extensive) MARK action. */
   15234                 :            :                         tag_be = mlx5_flow_mark_set
   15235                 :            :                               (((const struct rte_flow_action_mark *)
   15236         [ #  # ]:          0 :                                (actions->conf))->id);
   15237                 :            :                         MLX5_ASSERT(!handle->dvh.rix_tag);
   15238         [ #  # ]:          0 :                         if (flow_dv_tag_resource_register(dev, tag_be,
   15239                 :            :                                                           dev_flow, error))
   15240                 :          0 :                                 return -rte_errno;
   15241                 :            :                         MLX5_ASSERT(dev_flow->dv.tag_resource);
   15242                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15243                 :          0 :                                         dev_flow->dv.tag_resource->action;
   15244                 :          0 :                         break;
   15245                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_META:
   15246         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_meta
   15247                 :            :                                 (dev, mhdr_res, attr,
   15248                 :            :                                  (const struct rte_flow_action_set_meta *)
   15249                 :          0 :                                   actions->conf, error))
   15250                 :          0 :                                 return -rte_errno;
   15251                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_META;
   15252                 :          0 :                         break;
   15253                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TAG:
   15254         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_tag
   15255                 :            :                                 (dev, mhdr_res,
   15256                 :            :                                  (const struct rte_flow_action_set_tag *)
   15257                 :          0 :                                   actions->conf, error))
   15258                 :          0 :                                 return -rte_errno;
   15259                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15260                 :          0 :                         break;
   15261                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
   15262                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DROP;
   15263                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP;
   15264                 :          0 :                         break;
   15265                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
   15266                 :          0 :                         queue = actions->conf;
   15267                 :          0 :                         rss_desc->queue_num = 1;
   15268                 :          0 :                         rss_desc->queue[0] = queue->index;
   15269                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
   15270                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
   15271                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_QUEUE;
   15272                 :          0 :                         num_of_dest++;
   15273                 :          0 :                         break;
   15274                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
   15275                 :          0 :                         rss = actions->conf;
   15276                 :          0 :                         rss_desc->symmetric_hash_function =
   15277                 :          0 :                                 MLX5_RSS_IS_SYMM(rss->func);
   15278                 :          0 :                         memcpy(rss_desc->queue, rss->queue,
   15279         [ #  # ]:          0 :                                rss->queue_num * sizeof(uint16_t));
   15280                 :          0 :                         rss_desc->queue_num = rss->queue_num;
   15281                 :            :                         /* NULL RSS key indicates default RSS key. */
   15282         [ #  # ]:          0 :                         rss_key = !rss->key ? mlx5_rss_hash_default_key : rss->key;
   15283         [ #  # ]:          0 :                         memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   15284                 :            :                         /*
   15285                 :            :                          * rss->level and rss.types should be set in advance
   15286                 :            :                          * when expanding items for RSS.
   15287                 :            :                          */
   15288                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_RSS;
   15289                 :          0 :                         dev_flow->handle->fate_action = rss_desc->shared_rss ?
   15290         [ #  # ]:          0 :                                 MLX5_FLOW_FATE_SHARED_RSS :
   15291                 :            :                                 MLX5_FLOW_FATE_QUEUE;
   15292                 :          0 :                         break;
   15293                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_AGE:
   15294                 :          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15295                 :          0 :                         age_act = mlx5_flow_aso_age_get_by_idx(dev, owner_idx);
   15296         [ #  # ]:          0 :                         if (flow->age == 0) {
   15297                 :          0 :                                 flow->age = owner_idx;
   15298                 :          0 :                                 rte_atomic_fetch_add_explicit(&age_act->refcnt, 1,
   15299                 :            :                                                    rte_memory_order_relaxed);
   15300                 :            :                         }
   15301                 :          0 :                         age_act_pos = actions_n++;
   15302                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
   15303                 :          0 :                         break;
   15304                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
   15305                 :          0 :                         dev_flow->dv.actions[actions_n] =
   15306                 :          0 :                                 flow_dv_translate_action_send_to_kernel(dev, attr,
   15307                 :            :                                                         error);
   15308         [ #  # ]:          0 :                         if (!dev_flow->dv.actions[actions_n])
   15309                 :          0 :                                 return -rte_errno;
   15310                 :          0 :                         actions_n++;
   15311                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SEND_TO_KERNEL;
   15312                 :          0 :                         dev_flow->handle->fate_action =
   15313                 :            :                                         MLX5_FLOW_FATE_SEND_TO_KERNEL;
   15314                 :          0 :                         break;
   15315                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   15316                 :          0 :                         non_shared_age = action->conf;
   15317                 :          0 :                         age_act_pos = actions_n++;
   15318                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_AGE;
   15319                 :          0 :                         break;
   15320                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
   15321         [ #  # ]:          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15322                 :            :                         cnt_act = flow_dv_counter_get_by_idx(dev, owner_idx,
   15323                 :            :                                                              NULL);
   15324                 :            :                         MLX5_ASSERT(cnt_act != NULL);
   15325                 :            :                         /**
   15326                 :            :                          * When creating meter drop flow in drop table, the
   15327                 :            :                          * counter should not overwrite the rte flow counter.
   15328                 :            :                          */
   15329         [ #  # ]:          0 :                         if (attr->group == MLX5_FLOW_TABLE_LEVEL_METER &&
   15330         [ #  # ]:          0 :                             dev_flow->dv.table_id == MLX5_MTR_TABLE_ID_DROP) {
   15331                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15332                 :          0 :                                                         cnt_act->action;
   15333                 :            :                         } else {
   15334         [ #  # ]:          0 :                                 if (flow->counter == 0) {
   15335                 :          0 :                                         flow->counter = owner_idx;
   15336                 :          0 :                                         rte_atomic_fetch_add_explicit
   15337                 :            :                                                 (&cnt_act->shared_info.refcnt,
   15338                 :            :                                                  1, rte_memory_order_relaxed);
   15339                 :            :                                 }
   15340                 :            :                                 /* Save information first, will apply later. */
   15341                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_COUNT;
   15342                 :            :                         }
   15343                 :            :                         break;
   15344                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   15345         [ #  # ]:          0 :                         if (!priv->sh->cdev->config.devx) {
   15346                 :          0 :                                 return rte_flow_error_set
   15347                 :            :                                               (error, ENOTSUP,
   15348                 :            :                                                RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   15349                 :            :                                                NULL,
   15350                 :            :                                                "count action not supported");
   15351                 :            :                         }
   15352                 :            :                         /* Save information first, will apply later. */
   15353                 :          0 :                         count = action->conf;
   15354                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_COUNT;
   15355                 :          0 :                         break;
   15356                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
   15357                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15358                 :          0 :                                                 priv->sh->pop_vlan_action;
   15359                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
   15360                 :          0 :                         break;
   15361                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
   15362         [ #  # ]:          0 :                         if (!(action_flags &
   15363                 :            :                               MLX5_FLOW_ACTION_OF_SET_VLAN_VID))
   15364                 :          0 :                                 flow_dev_get_vlan_info_from_items(items, &vlan);
   15365         [ #  # ]:          0 :                         vlan.eth_proto = rte_be_to_cpu_16
   15366                 :            :                              ((((const struct rte_flow_action_of_push_vlan *)
   15367                 :            :                                                    actions->conf)->ethertype));
   15368                 :          0 :                         found_action = mlx5_flow_find_action
   15369                 :            :                                         (actions + 1,
   15370                 :            :                                          RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID);
   15371         [ #  # ]:          0 :                         if (found_action)
   15372                 :          0 :                                 mlx5_update_vlan_vid_pcp(found_action, &vlan);
   15373                 :          0 :                         found_action = mlx5_flow_find_action
   15374                 :            :                                         (actions + 1,
   15375                 :            :                                          RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP);
   15376         [ #  # ]:          0 :                         if (found_action)
   15377                 :          0 :                                 mlx5_update_vlan_vid_pcp(found_action, &vlan);
   15378         [ #  # ]:          0 :                         if (flow_dv_create_action_push_vlan
   15379                 :            :                                             (dev, attr, &vlan, dev_flow, error))
   15380                 :          0 :                                 return -rte_errno;
   15381                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15382                 :          0 :                                         dev_flow->dv.push_vlan_res->action;
   15383                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
   15384                 :          0 :                         break;
   15385                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
   15386                 :            :                         /* of_vlan_push action handled this action */
   15387                 :            :                         MLX5_ASSERT(action_flags &
   15388                 :            :                                     MLX5_FLOW_ACTION_OF_PUSH_VLAN);
   15389                 :            :                         break;
   15390                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
   15391         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
   15392                 :            :                                 break;
   15393                 :          0 :                         flow_dev_get_vlan_info_from_items(items, &vlan);
   15394                 :          0 :                         mlx5_update_vlan_vid_pcp(actions, &vlan);
   15395                 :            :                         /* If no VLAN push - this is a modify header action */
   15396         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_vlan_vid
   15397                 :            :                                                 (mhdr_res, actions, error))
   15398                 :          0 :                                 return -rte_errno;
   15399                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
   15400                 :          0 :                         break;
   15401                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
   15402                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
   15403         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_encap(dev, actions,
   15404                 :            :                                                            dev_flow,
   15405                 :          0 :                                                            attr->transfer,
   15406                 :            :                                                            error))
   15407                 :          0 :                                 return -rte_errno;
   15408                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15409                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15410                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   15411         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
   15412                 :          0 :                                 sample_act->action_flags |=
   15413                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15414                 :            :                         break;
   15415                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
   15416                 :            :                 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
   15417         [ #  # ]:          0 :                         if (flow_dv_create_action_l2_decap(dev, dev_flow,
   15418                 :          0 :                                                            attr->transfer,
   15419                 :            :                                                            error))
   15420                 :          0 :                                 return -rte_errno;
   15421                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15422                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15423                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   15424                 :          0 :                         break;
   15425                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
   15426                 :            :                         /* Handle encap with preceding decap. */
   15427         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_DECAP) {
   15428         [ #  # ]:          0 :                                 if (flow_dv_create_action_raw_encap
   15429                 :            :                                         (dev, actions, dev_flow, attr, error))
   15430                 :          0 :                                         return -rte_errno;
   15431                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15432                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15433                 :            :                         } else {
   15434                 :            :                                 /* Handle encap without preceding decap. */
   15435         [ #  # ]:          0 :                                 if (flow_dv_create_action_l2_encap
   15436                 :          0 :                                     (dev, actions, dev_flow, attr->transfer,
   15437                 :            :                                      error))
   15438                 :          0 :                                         return -rte_errno;
   15439                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15440                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15441                 :            :                         }
   15442                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_ENCAP;
   15443         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
   15444                 :          0 :                                 sample_act->action_flags |=
   15445                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15446                 :            :                         break;
   15447                 :            :                 case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
   15448         [ #  # ]:          0 :                         while ((++action)->type == RTE_FLOW_ACTION_TYPE_VOID)
   15449                 :            :                                 ;
   15450         [ #  # ]:          0 :                         if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
   15451         [ #  # ]:          0 :                                 if (flow_dv_create_action_l2_decap
   15452                 :          0 :                                     (dev, dev_flow, attr->transfer, error))
   15453                 :          0 :                                         return -rte_errno;
   15454                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15455                 :          0 :                                         dev_flow->dv.encap_decap->action;
   15456                 :            :                         }
   15457                 :            :                         /* If decap is followed by encap, handle it at encap. */
   15458                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DECAP;
   15459                 :          0 :                         break;
   15460                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_JUMP:
   15461                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15462                 :          0 :                                 (void *)(uintptr_t)action->conf;
   15463                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
   15464                 :          0 :                         break;
   15465                 :          0 :                 case RTE_FLOW_ACTION_TYPE_JUMP:
   15466                 :          0 :                         jump_group = ((const struct rte_flow_action_jump *)
   15467                 :          0 :                                                         action->conf)->group;
   15468                 :          0 :                         grp_info.std_tbl_fix = 0;
   15469         [ #  # ]:          0 :                         if (dev_flow->skip_scale &
   15470                 :            :                                 (1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT))
   15471                 :          0 :                                 grp_info.skip_scale = 1;
   15472                 :            :                         else
   15473                 :          0 :                                 grp_info.skip_scale = 0;
   15474                 :          0 :                         ret = mlx5_flow_group_to_table(dev, tunnel,
   15475                 :            :                                                        jump_group,
   15476                 :            :                                                        &table,
   15477                 :            :                                                        &grp_info, error);
   15478         [ #  # ]:          0 :                         if (ret)
   15479                 :          0 :                                 return ret;
   15480                 :          0 :                         tbl = mlx5_flow_dv_tbl_resource_get(dev, table, attr->egress,
   15481                 :          0 :                                                             attr->transfer,
   15482                 :          0 :                                                             dev_flow->external,
   15483                 :            :                                                             tunnel, jump_group, 0,
   15484                 :            :                                                             0, error);
   15485         [ #  # ]:          0 :                         if (!tbl)
   15486                 :          0 :                                 return rte_flow_error_set
   15487                 :          0 :                                                 (error, errno,
   15488                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
   15489                 :            :                                                  NULL,
   15490                 :            :                                                  "cannot create jump action.");
   15491                 :            :                         if (flow_dv_jump_tbl_resource_register
   15492                 :            :                             (dev, tbl, dev_flow, error)) {
   15493                 :            :                                 mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   15494                 :            :                                 return rte_flow_error_set
   15495                 :            :                                                 (error, errno,
   15496                 :            :                                                  RTE_FLOW_ERROR_TYPE_ACTION,
   15497                 :            :                                                  NULL,
   15498                 :            :                                                  "cannot create jump action.");
   15499                 :            :                         }
   15500                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15501                 :          0 :                                         dev_flow->dv.jump->action;
   15502                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_JUMP;
   15503                 :          0 :                         dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP;
   15504                 :          0 :                         sample_act->action_flags |= MLX5_FLOW_ACTION_JUMP;
   15505                 :          0 :                         num_of_dest++;
   15506                 :          0 :                         break;
   15507                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
   15508                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
   15509         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_mac
   15510                 :            :                                         (mhdr_res, actions, error))
   15511                 :          0 :                                 return -rte_errno;
   15512                 :          0 :                         action_flags |= actions->type ==
   15513                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
   15514         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_MAC_SRC :
   15515                 :            :                                         MLX5_FLOW_ACTION_SET_MAC_DST;
   15516                 :          0 :                         break;
   15517                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
   15518                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
   15519         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv4
   15520                 :            :                                         (mhdr_res, actions, error))
   15521                 :          0 :                                 return -rte_errno;
   15522                 :          0 :                         action_flags |= actions->type ==
   15523                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
   15524         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_IPV4_SRC :
   15525                 :            :                                         MLX5_FLOW_ACTION_SET_IPV4_DST;
   15526                 :          0 :                         break;
   15527                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
   15528                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
   15529         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv6
   15530                 :            :                                         (mhdr_res, actions, error))
   15531                 :          0 :                                 return -rte_errno;
   15532                 :          0 :                         action_flags |= actions->type ==
   15533                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
   15534         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_IPV6_SRC :
   15535                 :            :                                         MLX5_FLOW_ACTION_SET_IPV6_DST;
   15536                 :          0 :                         break;
   15537                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
   15538                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
   15539         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tp
   15540                 :            :                                         (mhdr_res, actions, items,
   15541                 :          0 :                                          &flow_attr, dev_flow, !!(action_flags &
   15542                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15543                 :          0 :                                 return -rte_errno;
   15544                 :          0 :                         action_flags |= actions->type ==
   15545                 :            :                                         RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
   15546         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_SET_TP_SRC :
   15547                 :            :                                         MLX5_FLOW_ACTION_SET_TP_DST;
   15548                 :          0 :                         break;
   15549                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DEC_TTL:
   15550         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_dec_ttl
   15551                 :            :                                         (mhdr_res, items, &flow_attr, dev_flow,
   15552                 :          0 :                                          !!(action_flags &
   15553                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15554                 :          0 :                                 return -rte_errno;
   15555                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEC_TTL;
   15556                 :          0 :                         break;
   15557                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_TTL:
   15558         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ttl
   15559                 :            :                                         (mhdr_res, actions, items, &flow_attr,
   15560                 :          0 :                                          dev_flow, !!(action_flags &
   15561                 :            :                                          MLX5_FLOW_ACTION_DECAP), error))
   15562                 :          0 :                                 return -rte_errno;
   15563                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TTL;
   15564                 :          0 :                         break;
   15565                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
   15566                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
   15567         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tcp_seq
   15568                 :            :                                         (mhdr_res, actions, error))
   15569                 :          0 :                                 return -rte_errno;
   15570                 :          0 :                         action_flags |= actions->type ==
   15571                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
   15572         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_INC_TCP_SEQ :
   15573                 :            :                                         MLX5_FLOW_ACTION_DEC_TCP_SEQ;
   15574                 :          0 :                         break;
   15575                 :            : 
   15576                 :          0 :                 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
   15577                 :            :                 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
   15578         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_tcp_ack
   15579                 :            :                                         (mhdr_res, actions, error))
   15580                 :          0 :                                 return -rte_errno;
   15581                 :          0 :                         action_flags |= actions->type ==
   15582                 :            :                                         RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
   15583         [ #  # ]:          0 :                                         MLX5_FLOW_ACTION_INC_TCP_ACK :
   15584                 :            :                                         MLX5_FLOW_ACTION_DEC_TCP_ACK;
   15585                 :          0 :                         break;
   15586                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
   15587         [ #  # ]:          0 :                         if (flow_dv_convert_action_set_reg
   15588                 :            :                                         (mhdr_res, actions, error))
   15589                 :          0 :                                 return -rte_errno;
   15590                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15591                 :          0 :                         break;
   15592                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
   15593         [ #  # ]:          0 :                         if (flow_dv_convert_action_copy_mreg
   15594                 :            :                                         (dev, mhdr_res, actions, error))
   15595                 :          0 :                                 return -rte_errno;
   15596                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   15597                 :          0 :                         break;
   15598                 :          0 :                 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
   15599                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS;
   15600                 :          0 :                         dev_flow->handle->fate_action =
   15601                 :            :                                         MLX5_FLOW_FATE_DEFAULT_MISS;
   15602                 :          0 :                         break;
   15603                 :          0 :                 case RTE_FLOW_ACTION_TYPE_METER:
   15604         [ #  # ]:          0 :                         if (!wks->fm)
   15605                 :          0 :                                 return rte_flow_error_set(error, rte_errno,
   15606                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION,
   15607                 :            :                                         NULL, "Failed to get meter in flow.");
   15608                 :            :                         /* Set the meter action. */
   15609                 :          0 :                         dev_flow->dv.actions[actions_n++] =
   15610                 :          0 :                                 wks->fm->meter_action_g;
   15611                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_METER;
   15612                 :          0 :                         break;
   15613                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
   15614         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv4_dscp(mhdr_res,
   15615                 :            :                                                               actions, error))
   15616                 :          0 :                                 return -rte_errno;
   15617                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP;
   15618                 :          0 :                         break;
   15619                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
   15620         [ #  # ]:          0 :                         if (mlx5_dv_modify_ipv6_traffic_class_supported(priv))
   15621                 :            :                                 ipv6_tc_off = MLX5_IPV6_HDR_DSCP_SHIFT;
   15622                 :            :                         else
   15623                 :            :                                 ipv6_tc_off = 0;
   15624         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_ipv6_dscp(mhdr_res,
   15625                 :            :                                                               actions, ipv6_tc_off, error))
   15626                 :          0 :                                 return -rte_errno;
   15627                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
   15628                 :          0 :                         break;
   15629                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SAMPLE:
   15630                 :          0 :                         sample_act_pos = actions_n;
   15631                 :          0 :                         sample = (const struct rte_flow_action_sample *)
   15632                 :            :                                  action->conf;
   15633                 :          0 :                         actions_n++;
   15634                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_SAMPLE;
   15635                 :            :                         /* put encap action into group if work with port id */
   15636         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_ENCAP) &&
   15637                 :            :                             (action_flags & MLX5_FLOW_ACTION_PORT_ID))
   15638                 :          0 :                                 sample_act->action_flags |=
   15639                 :            :                                                         MLX5_FLOW_ACTION_ENCAP;
   15640                 :            :                         break;
   15641                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   15642         [ #  # ]:          0 :                         if (flow_dv_convert_action_modify_field
   15643                 :            :                                         (dev, mhdr_res, actions, attr, error))
   15644                 :          0 :                                 return -rte_errno;
   15645                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   15646                 :          0 :                         break;
   15647                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   15648                 :          0 :                         owner_idx = (uint32_t)(uintptr_t)action->conf;
   15649                 :          0 :                         ct = flow_aso_ct_get_by_idx(dev, owner_idx);
   15650         [ #  # ]:          0 :                         if (!ct)
   15651                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
   15652                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15653                 :            :                                                 NULL,
   15654                 :            :                                                 "Failed to get CT object.");
   15655         [ #  # ]:          0 :                         if (mlx5_aso_ct_available(priv->sh, MLX5_HW_INV_QUEUE, ct))
   15656                 :          0 :                                 return rte_flow_error_set(error, rte_errno,
   15657                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15658                 :            :                                                 NULL,
   15659                 :            :                                                 "CT is unavailable.");
   15660         [ #  # ]:          0 :                         if (ct->is_original)
   15661                 :          0 :                                 dev_flow->dv.actions[actions_n] =
   15662                 :          0 :                                                         ct->dr_action_orig;
   15663                 :            :                         else
   15664                 :          0 :                                 dev_flow->dv.actions[actions_n] =
   15665                 :          0 :                                                         ct->dr_action_rply;
   15666         [ #  # ]:          0 :                         if (flow->ct == 0) {
   15667                 :          0 :                                 flow->indirect_type =
   15668                 :            :                                                 MLX5_INDIRECT_ACTION_TYPE_CT;
   15669                 :          0 :                                 flow->ct = owner_idx;
   15670                 :          0 :                                 rte_atomic_fetch_add_explicit(&ct->refcnt, 1,
   15671                 :            :                                                    rte_memory_order_relaxed);
   15672                 :            :                         }
   15673                 :          0 :                         actions_n++;
   15674                 :          0 :                         action_flags |= MLX5_FLOW_ACTION_CT;
   15675                 :          0 :                         break;
   15676                 :          0 :                 case RTE_FLOW_ACTION_TYPE_END:
   15677                 :            :                         actions_end = true;
   15678         [ #  # ]:          0 :                         if (mhdr_res->actions_num) {
   15679                 :            :                                 /* create modify action if needed. */
   15680         [ #  # ]:          0 :                                 if (flow_dv_modify_hdr_resource_register
   15681                 :            :                                         (dev, mhdr_res, dev_flow, error))
   15682                 :          0 :                                         return -rte_errno;
   15683                 :          0 :                                 dev_flow->dv.actions[modify_action_position] =
   15684                 :          0 :                                         handle->dvh.modify_hdr->action;
   15685                 :            :                         }
   15686                 :            :                         /*
   15687                 :            :                          * Handle AGE and COUNT action by single HW counter
   15688                 :            :                          * when they are not shared.
   15689                 :            :                          */
   15690         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_AGE) {
   15691   [ #  #  #  # ]:          0 :                                 if ((non_shared_age && count) ||
   15692         [ #  # ]:          0 :                                     !flow_hit_aso_supported(priv, !dev_flow->dv.group)) {
   15693                 :            :                                         /* Creates age by counters. */
   15694                 :          0 :                                         cnt_act = flow_dv_prepare_counter
   15695                 :            :                                                                 (dev, dev_flow,
   15696                 :            :                                                                  flow, count,
   15697                 :            :                                                                  non_shared_age,
   15698                 :            :                                                                  error);
   15699         [ #  # ]:          0 :                                         if (!cnt_act)
   15700                 :          0 :                                                 return -rte_errno;
   15701                 :          0 :                                         dev_flow->dv.actions[age_act_pos] =
   15702                 :          0 :                                                                 cnt_act->action;
   15703                 :          0 :                                         break;
   15704                 :            :                                 }
   15705   [ #  #  #  # ]:          0 :                                 if (!flow->age && non_shared_age) {
   15706                 :          0 :                                         flow->age = flow_dv_aso_age_alloc
   15707                 :            :                                                                 (dev, error);
   15708         [ #  # ]:          0 :                                         if (!flow->age)
   15709                 :          0 :                                                 return -rte_errno;
   15710                 :          0 :                                         flow_dv_aso_age_params_init
   15711                 :            :                                                     (dev, flow->age,
   15712                 :          0 :                                                      non_shared_age->context ?
   15713                 :            :                                                      non_shared_age->context :
   15714                 :          0 :                                                      (void *)(uintptr_t)
   15715                 :          0 :                                                      (dev_flow->flow_idx),
   15716         [ #  # ]:          0 :                                                      non_shared_age->timeout);
   15717                 :            :                                 }
   15718                 :          0 :                                 age_act = mlx5_flow_aso_age_get_by_idx(dev, flow->age);
   15719                 :          0 :                                 dev_flow->dv.actions[age_act_pos] =
   15720                 :          0 :                                                              age_act->dr_action;
   15721                 :            :                         }
   15722         [ #  # ]:          0 :                         if (action_flags & MLX5_FLOW_ACTION_COUNT) {
   15723                 :            :                                 /*
   15724                 :            :                                  * Create one count action, to be used
   15725                 :            :                                  * by all sub-flows.
   15726                 :            :                                  */
   15727                 :          0 :                                 cnt_act = flow_dv_prepare_counter(dev, dev_flow,
   15728                 :            :                                                                   flow, count,
   15729                 :            :                                                                   NULL, error);
   15730         [ #  # ]:          0 :                                 if (!cnt_act)
   15731                 :          0 :                                         return -rte_errno;
   15732                 :          0 :                                 dev_flow->dv.actions[actions_n++] =
   15733                 :          0 :                                                                 cnt_act->action;
   15734                 :            :                         }
   15735                 :            :                 default:
   15736                 :            :                         break;
   15737                 :            :                 }
   15738   [ #  #  #  # ]:          0 :                 if (mhdr_res->actions_num &&
   15739                 :            :                     modify_action_position == UINT32_MAX)
   15740                 :          0 :                         modify_action_position = actions_n++;
   15741                 :            :         }
   15742                 :          0 :         dev_flow->act_flags = action_flags;
   15743                 :          0 :         ret = flow_dv_translate_items_sws(dev, dev_flow, attr, items, &matcher,
   15744                 :            :                                       error);
   15745         [ #  # ]:          0 :         if (ret)
   15746                 :          0 :                 return -rte_errno;
   15747         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_RSS) {
   15748                 :          0 :                 dev_flow->symmetric_hash_function = rss_desc->symmetric_hash_function;
   15749                 :          0 :                 mlx5_flow_dv_hashfields_set(dev_flow->handle->layers,
   15750                 :            :                                             rss_desc,
   15751                 :            :                                             &dev_flow->hash_fields);
   15752                 :            :         }
   15753                 :            :         /* If has RSS action in the sample action, the Sample/Mirror resource
   15754                 :            :          * should be registered after the hash filed be update.
   15755                 :            :          */
   15756         [ #  # ]:          0 :         if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
   15757                 :          0 :                 ret = flow_dv_translate_action_sample(dev,
   15758                 :            :                                                       sample,
   15759                 :            :                                                       dev_flow, attr,
   15760                 :            :                                                       &num_of_dest,
   15761                 :            :                                                       sample_actions,
   15762                 :            :                                                       &sample_res,
   15763                 :            :                                                       error);
   15764         [ #  # ]:          0 :                 if (ret < 0)
   15765                 :            :                         return ret;
   15766                 :          0 :                 ret = flow_dv_create_action_sample(dev,
   15767                 :            :                                                    dev_flow,
   15768                 :            :                                                    num_of_dest,
   15769                 :            :                                                    &sample_res,
   15770                 :            :                                                    &mdest_res,
   15771                 :            :                                                    sample_actions,
   15772                 :            :                                                    action_flags,
   15773                 :            :                                                    error);
   15774         [ #  # ]:          0 :                 if (ret < 0)
   15775                 :          0 :                         return rte_flow_error_set
   15776                 :            :                                                 (error, rte_errno,
   15777                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
   15778                 :            :                                                 NULL,
   15779                 :            :                                                 "cannot create sample action");
   15780         [ #  # ]:          0 :                 if (num_of_dest > 1) {
   15781                 :          0 :                         dev_flow->dv.actions[sample_act_pos] =
   15782                 :          0 :                         dev_flow->dv.dest_array_res->action;
   15783                 :            :                 } else {
   15784                 :          0 :                         dev_flow->dv.actions[sample_act_pos] =
   15785                 :          0 :                         dev_flow->dv.sample_res->verbs_action;
   15786                 :            :                 }
   15787                 :            :         }
   15788                 :            :         /*
   15789                 :            :          * For multiple destination (sample action with ratio=1), the encap
   15790                 :            :          * action and port id action will be combined into group action.
   15791                 :            :          * So need remove the original these actions in the flow and only
   15792                 :            :          * use the sample action instead of.
   15793                 :            :          */
   15794         [ #  # ]:          0 :         if (num_of_dest > 1 &&
   15795   [ #  #  #  # ]:          0 :             (sample_act->dr_port_id_action || sample_act->dr_jump_action)) {
   15796                 :            :                 int i;
   15797                 :          0 :                 void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
   15798                 :            : 
   15799         [ #  # ]:          0 :                 for (i = 0; i < actions_n; i++) {
   15800         [ #  # ]:          0 :                         if ((sample_act->dr_encap_action &&
   15801                 :            :                                 sample_act->dr_encap_action ==
   15802   [ #  #  #  # ]:          0 :                                 dev_flow->dv.actions[i]) ||
   15803                 :          0 :                                 (sample_act->dr_port_id_action &&
   15804                 :            :                                 sample_act->dr_port_id_action ==
   15805         [ #  # ]:          0 :                                 dev_flow->dv.actions[i]) ||
   15806         [ #  # ]:          0 :                                 (sample_act->dr_jump_action &&
   15807                 :            :                                 sample_act->dr_jump_action ==
   15808         [ #  # ]:          0 :                                 dev_flow->dv.actions[i]))
   15809                 :          0 :                                 continue;
   15810                 :          0 :                         temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];
   15811                 :            :                 }
   15812                 :          0 :                 memcpy((void *)dev_flow->dv.actions,
   15813                 :            :                                 (void *)temp_actions,
   15814                 :            :                                 tmp_actions_n * sizeof(void *));
   15815                 :            :                 actions_n = tmp_actions_n;
   15816                 :            :         }
   15817                 :          0 :         dev_flow->dv.actions_n = actions_n;
   15818         [ #  # ]:          0 :         if (wks->skip_matcher_reg)
   15819                 :            :                 return 0;
   15820                 :            :         /* Register matcher. */
   15821                 :          0 :         matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
   15822                 :            :                                     matcher.mask.size);
   15823                 :          0 :         matcher.priority = mlx5_get_matcher_priority(dev, attr,
   15824                 :          0 :                                                      matcher.priority,
   15825                 :          0 :                                                      dev_flow->external);
   15826                 :            :         /**
   15827                 :            :          * When creating meter drop flow in drop table, using original
   15828                 :            :          * 5-tuple match, the matcher priority should be lower than
   15829                 :            :          * mtr_id matcher.
   15830                 :            :          */
   15831         [ #  # ]:          0 :         if (attr->group == MLX5_FLOW_TABLE_LEVEL_METER &&
   15832   [ #  #  #  # ]:          0 :             dev_flow->dv.table_id == MLX5_MTR_TABLE_ID_DROP &&
   15833                 :            :             matcher.priority <= MLX5_REG_BITS)
   15834                 :          0 :                 matcher.priority += MLX5_REG_BITS;
   15835                 :            :         /* reserved field no needs to be set to 0 here. */
   15836                 :          0 :         tbl_key.is_fdb = attr->transfer;
   15837                 :          0 :         tbl_key.is_egress = attr->egress;
   15838                 :          0 :         tbl_key.level = dev_flow->dv.group;
   15839                 :          0 :         tbl_key.id = dev_flow->dv.table_id;
   15840         [ #  # ]:          0 :         if (flow_dv_matcher_register(dev, &matcher, &tbl_key, dev_flow,
   15841                 :            :                                      tunnel, attr->group, error))
   15842                 :          0 :                 return -rte_errno;
   15843                 :            :         return 0;
   15844                 :            : }
   15845                 :            : 
   15846                 :            : /*
   15847                 :            :  * Protocol selector bitmap
   15848                 :            :  * Each flag is used as an indicator that given protocol is specified in given RSS hash fields.
   15849                 :            :  */
   15850                 :            : #define RX_HASH_SELECTOR_IPV4 RTE_BIT32(0)
   15851                 :            : #define RX_HASH_SELECTOR_IPV6 RTE_BIT32(1)
   15852                 :            : #define RX_HASH_SELECTOR_UDP RTE_BIT32(2)
   15853                 :            : #define RX_HASH_SELECTOR_TCP RTE_BIT32(3)
   15854                 :            : #define RX_HASH_SELECTOR_ESP_SPI RTE_BIT32(4)
   15855                 :            : #define RX_HASH_SELECTOR_NONE (0)
   15856                 :            : 
   15857                 :            : #define RX_HASH_SELECTOR_IPV4_TCP (RX_HASH_SELECTOR_IPV4 | RX_HASH_SELECTOR_TCP)
   15858                 :            : #define RX_HASH_SELECTOR_IPV4_UDP (RX_HASH_SELECTOR_IPV4 | RX_HASH_SELECTOR_UDP)
   15859                 :            : #define RX_HASH_SELECTOR_IPV4_ESP (RX_HASH_SELECTOR_IPV4 | RX_HASH_SELECTOR_ESP_SPI)
   15860                 :            : 
   15861                 :            : #define RX_HASH_SELECTOR_IPV6_TCP (RX_HASH_SELECTOR_IPV6 | RX_HASH_SELECTOR_TCP)
   15862                 :            : #define RX_HASH_SELECTOR_IPV6_UDP (RX_HASH_SELECTOR_IPV6 | RX_HASH_SELECTOR_UDP)
   15863                 :            : #define RX_HASH_SELECTOR_IPV6_ESP (RX_HASH_SELECTOR_IPV6 | RX_HASH_SELECTOR_ESP_SPI)
   15864                 :            : 
   15865                 :            : static bool
   15866                 :            : rx_hash_selector_has_valid_l3(const uint32_t selectors)
   15867                 :            : {
   15868                 :            :         /* In TIR configuration, RSS hashing on both IPv4 and IPv6 is mutually exclusive. */
   15869                 :            :         return !((selectors & RX_HASH_SELECTOR_IPV4) && (selectors & RX_HASH_SELECTOR_IPV6));
   15870                 :            : }
   15871                 :            : 
   15872                 :            : static bool
   15873                 :            : rx_hash_selector_has_valid_l4(const uint32_t selectors)
   15874                 :            : {
   15875                 :            :         /* In TIR configuration, RSS hashing on both UDP and TCP is mutually exclusive. */
   15876                 :          0 :         return !((selectors & RX_HASH_SELECTOR_UDP) && (selectors & RX_HASH_SELECTOR_TCP));
   15877                 :            : }
   15878                 :            : 
   15879                 :            : static bool
   15880                 :            : rx_hash_selector_has_valid_esp(const uint32_t selectors)
   15881                 :            : {
   15882                 :            :         /* In TIR configuration, RSS hashing on ESP and other L4 protocol is mutually exclusive. */
   15883         [ #  # ]:          0 :         if (selectors & RX_HASH_SELECTOR_ESP_SPI)
   15884                 :          0 :                 return !((selectors & RX_HASH_SELECTOR_UDP) || (selectors & RX_HASH_SELECTOR_TCP));
   15885                 :            : 
   15886                 :            :         return true;
   15887                 :            : }
   15888                 :            : 
   15889                 :            : /**
   15890                 :            :  * Calculate protocol combination based on provided RSS hashing fields.
   15891                 :            :  *
   15892                 :            :  * @param[in] hash_fields
   15893                 :            :  *   Requested RSS hashing fields specified as a flags bitmap, based on ibv_rx_hash_fields.
   15894                 :            :  * @param[out] selectors_out
   15895                 :            :  *   Calculated protocol combination will be written here.
   15896                 :            :  *   Result will be a bitmap of RX_HASH_SELECTOR_* flags.
   15897                 :            :  *
   15898                 :            :  * @return
   15899                 :            :  *   0 if conversion is successful and protocol combination written to @p selectors_out.
   15900                 :            :  *   (-EINVAL) otherwise.
   15901                 :            :  */
   15902                 :            : static int
   15903                 :          0 : rx_hash_calc_selector(const uint64_t hash_fields, uint32_t *selectors_out)
   15904                 :            : {
   15905                 :            :         const uint64_t filtered_hf = hash_fields & ~IBV_RX_HASH_INNER;
   15906                 :            :         uint32_t selectors = 0;
   15907                 :            : 
   15908         [ #  # ]:          0 :         if (filtered_hf & MLX5_RSS_HASH_IPV4)
   15909                 :            :                 selectors |= RX_HASH_SELECTOR_IPV4;
   15910         [ #  # ]:          0 :         if (filtered_hf & MLX5_RSS_HASH_IPV6)
   15911                 :          0 :                 selectors |= RX_HASH_SELECTOR_IPV6;
   15912         [ #  # ]:          0 :         if (!rx_hash_selector_has_valid_l3(selectors)) {
   15913                 :          0 :                 DRV_LOG(NOTICE, "hrxq hashing on both IPv4 and IPv6 is invalid: "
   15914                 :            :                                 "selectors=0x%" PRIx32, selectors);
   15915                 :          0 :                 return -EINVAL;
   15916                 :            :         }
   15917                 :            : 
   15918         [ #  # ]:          0 :         if (filtered_hf & MLX5_UDP_IBV_RX_HASH)
   15919                 :          0 :                 selectors |= RX_HASH_SELECTOR_UDP;
   15920         [ #  # ]:          0 :         if (filtered_hf & MLX5_TCP_IBV_RX_HASH)
   15921                 :          0 :                 selectors |= RX_HASH_SELECTOR_TCP;
   15922         [ #  # ]:          0 :         if (!rx_hash_selector_has_valid_l4(selectors)) {
   15923                 :          0 :                 DRV_LOG(NOTICE, "hrxq hashing on both UDP and TCP is invalid: "
   15924                 :            :                                 "selectors=0x%" PRIx32, selectors);
   15925                 :          0 :                 return -EINVAL;
   15926                 :            :         }
   15927                 :            : 
   15928         [ #  # ]:          0 :         if (filtered_hf & MLX5_RSS_HASH_ESP_SPI)
   15929                 :          0 :                 selectors |= RX_HASH_SELECTOR_ESP_SPI;
   15930         [ #  # ]:          0 :         if (!rx_hash_selector_has_valid_esp(selectors)) {
   15931                 :          0 :                 DRV_LOG(NOTICE, "hrxq hashing on ESP SPI and UDP or TCP is mutually exclusive: "
   15932                 :            :                                 "selectors=0x%" PRIx32, selectors);
   15933                 :          0 :                 return -EINVAL;
   15934                 :            :         }
   15935                 :            : 
   15936                 :          0 :         *selectors_out = selectors;
   15937                 :          0 :         return 0;
   15938                 :            : }
   15939                 :            : 
   15940                 :            : /**
   15941                 :            :  * Calculate the hrxq object index based on protocol combination.
   15942                 :            :  *
   15943                 :            :  * @param[in] selectors
   15944                 :            :  *   Protocol combination specified as bitmap of RX_HASH_SELECTOR_* flags.
   15945                 :            :  *
   15946                 :            :  * @return
   15947                 :            :  *   Index into hrxq array in #mlx5_shared_action_rss based on ginve protocol combination.
   15948                 :            :  *   (-EINVAL) if given protocol combination is not supported or is invalid.
   15949                 :            :  */
   15950                 :            : static int
   15951                 :          0 : get_rss_hash_idx(const uint32_t selectors)
   15952                 :            : {
   15953   [ #  #  #  #  :          0 :         switch (selectors) {
          #  #  #  #  #  
             #  #  #  # ]
   15954                 :            :         case RX_HASH_SELECTOR_IPV4:
   15955                 :            :                 return MLX5_RSS_HASH_IDX_IPV4;
   15956                 :          0 :         case RX_HASH_SELECTOR_IPV4_TCP:
   15957                 :          0 :                 return MLX5_RSS_HASH_IDX_IPV4_TCP;
   15958                 :          0 :         case RX_HASH_SELECTOR_IPV4_UDP:
   15959                 :          0 :                 return MLX5_RSS_HASH_IDX_IPV4_UDP;
   15960                 :          0 :         case RX_HASH_SELECTOR_IPV4_ESP:
   15961                 :          0 :                 return MLX5_RSS_HASH_IDX_IPV4_ESP;
   15962                 :          0 :         case RX_HASH_SELECTOR_IPV6:
   15963                 :          0 :                 return MLX5_RSS_HASH_IDX_IPV6;
   15964                 :          0 :         case RX_HASH_SELECTOR_IPV6_TCP:
   15965                 :          0 :                 return MLX5_RSS_HASH_IDX_IPV6_TCP;
   15966                 :          0 :         case RX_HASH_SELECTOR_IPV6_UDP:
   15967                 :          0 :                 return MLX5_RSS_HASH_IDX_IPV6_UDP;
   15968                 :          0 :         case RX_HASH_SELECTOR_IPV6_ESP:
   15969                 :          0 :                 return MLX5_RSS_HASH_IDX_IPV6_ESP;
   15970                 :          0 :         case RX_HASH_SELECTOR_TCP:
   15971                 :          0 :                 return MLX5_RSS_HASH_IDX_TCP;
   15972                 :          0 :         case RX_HASH_SELECTOR_UDP:
   15973                 :          0 :                 return MLX5_RSS_HASH_IDX_UDP;
   15974                 :          0 :         case RX_HASH_SELECTOR_ESP_SPI:
   15975                 :          0 :                 return MLX5_RSS_HASH_IDX_ESP_SPI;
   15976                 :          0 :         case RX_HASH_SELECTOR_NONE:
   15977                 :          0 :                 return MLX5_RSS_HASH_IDX_NONE;
   15978                 :          0 :         default:
   15979                 :          0 :                 DRV_LOG(ERR, "invalid hrxq hash fields combination: "
   15980                 :            :                              "selectors=0x%" PRIx32, selectors);
   15981                 :          0 :                 return -EINVAL;
   15982                 :            :         }
   15983                 :            : }
   15984                 :            : 
   15985                 :            : /**
   15986                 :            :  * Set hash RX queue by hash fields (see enum ibv_rx_hash_fields)
   15987                 :            :  * and tunnel.
   15988                 :            :  *
   15989                 :            :  * @param[in, out] action
   15990                 :            :  *   Shred RSS action holding hash RX queue objects.
   15991                 :            :  * @param[in] hash_fields
   15992                 :            :  *   Defines combination of packet fields to participate in RX hash,
   15993                 :            :  *   specified as a bitmap of #ibv_rx_hash_fields flags.
   15994                 :            :  * @param[in] tunnel
   15995                 :            :  *   Tunnel type
   15996                 :            :  * @param[in] hrxq_idx
   15997                 :            :  *   Hash RX queue index to set.
   15998                 :            :  *
   15999                 :            :  * @return
   16000                 :            :  *   0 on success, otherwise negative errno value.
   16001                 :            :  */
   16002                 :            : static int
   16003                 :          0 : __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
   16004                 :            :                               const uint64_t hash_fields,
   16005                 :            :                               uint32_t hrxq_idx)
   16006                 :            : {
   16007                 :          0 :         uint32_t *hrxqs = action->hrxq;
   16008                 :          0 :         uint32_t selectors = 0;
   16009                 :            :         int ret;
   16010                 :            : 
   16011                 :          0 :         ret = rx_hash_calc_selector(hash_fields, &selectors);
   16012                 :            :         /*
   16013                 :            :          * Hash fields passed to this function are constructed internally.
   16014                 :            :          * If this fails, then this is a PMD bug.
   16015                 :            :          */
   16016                 :            :         MLX5_ASSERT(ret == 0);
   16017                 :            : 
   16018                 :          0 :         ret = get_rss_hash_idx(selectors);
   16019                 :            :         /*
   16020                 :            :          * Based on above assert, selectors should always yield correct index
   16021                 :            :          * in mlx5_rss_hash_fields array.
   16022                 :            :          * If this fails, then this is a PMD bug.
   16023                 :            :          */
   16024                 :            :         MLX5_ASSERT(ret >= 0 && ret < MLX5_RSS_HASH_IDX_MAX);
   16025                 :          0 :         hrxqs[ret] = hrxq_idx;
   16026                 :            : 
   16027                 :          0 :         return 0;
   16028                 :            : }
   16029                 :            : 
   16030                 :            : /**
   16031                 :            :  * Look up for hash RX queue by hash fields (see enum ibv_rx_hash_fields)
   16032                 :            :  * and tunnel.
   16033                 :            :  *
   16034                 :            :  * @param[in] dev
   16035                 :            :  *   Pointer to the Ethernet device structure.
   16036                 :            :  * @param[in] idx
   16037                 :            :  *   Shared RSS action ID holding hash RX queue objects.
   16038                 :            :  * @param[in] hash_fields
   16039                 :            :  *   Defines combination of packet fields to participate in RX hash,
   16040                 :            :  *   specified as a bitmap of #ibv_rx_hash_fields flags.
   16041                 :            :  * @param[in] tunnel
   16042                 :            :  *   Tunnel type
   16043                 :            :  *
   16044                 :            :  * @return
   16045                 :            :  *   Valid hash RX queue index, otherwise 0.
   16046                 :            :  */
   16047                 :            : uint32_t
   16048                 :          0 : mlx5_flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
   16049                 :            :                                     const uint64_t hash_fields)
   16050                 :            : {
   16051                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16052                 :            :         struct mlx5_shared_action_rss *shared_rss =
   16053                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   16054                 :            :         const uint32_t *hrxqs;
   16055                 :          0 :         uint32_t selectors = 0;
   16056                 :            :         int ret;
   16057                 :            : 
   16058         [ #  # ]:          0 :         if (!shared_rss) {
   16059                 :          0 :                 DRV_LOG(ERR, "port %u cannot get RSS action: rss_act_idx=%u",
   16060                 :            :                         dev->data->port_id, idx);
   16061                 :          0 :                 return 0;
   16062                 :            :         }
   16063                 :          0 :         hrxqs = shared_rss->hrxq;
   16064                 :            : 
   16065                 :          0 :         ret = rx_hash_calc_selector(hash_fields, &selectors);
   16066         [ #  # ]:          0 :         if (ret < 0) {
   16067                 :          0 :                 DRV_LOG(ERR, "port %u Rx hash selector calculation failed: "
   16068                 :            :                              "rss_act_idx=%u hash_fields=0x%" PRIx64 " selectors=0x%" PRIx32,
   16069                 :            :                         dev->data->port_id, idx, hash_fields, selectors);
   16070                 :          0 :                 return 0;
   16071                 :            :         }
   16072                 :            : 
   16073                 :          0 :         ret = get_rss_hash_idx(selectors);
   16074         [ #  # ]:          0 :         if (ret < 0) {
   16075                 :          0 :                 DRV_LOG(ERR, "port %u failed hrxq index lookup: "
   16076                 :            :                              "rss_act_idx=%u hash_fields=0x%" PRIx64 " selectors=0x%" PRIx32,
   16077                 :            :                         dev->data->port_id, idx, hash_fields, selectors);
   16078                 :          0 :                 return 0;
   16079                 :            :         }
   16080                 :            : 
   16081                 :          0 :         return hrxqs[ret];
   16082                 :            : }
   16083                 :            : 
   16084                 :            : /**
   16085                 :            :  * Apply the flow to the NIC, lock free,
   16086                 :            :  * (mutex should be acquired by caller).
   16087                 :            :  *
   16088                 :            :  * @param[in] dev
   16089                 :            :  *   Pointer to the Ethernet device structure.
   16090                 :            :  * @param[in, out] flow
   16091                 :            :  *   Pointer to flow structure.
   16092                 :            :  * @param[out] error
   16093                 :            :  *   Pointer to error structure.
   16094                 :            :  *
   16095                 :            :  * @return
   16096                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   16097                 :            :  */
   16098                 :            : static int
   16099                 :          0 : flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
   16100                 :            :               struct rte_flow_error *error)
   16101                 :            : {
   16102                 :            :         struct mlx5_flow_dv_workspace *dv;
   16103                 :            :         struct mlx5_flow_handle *dh;
   16104                 :            :         struct mlx5_flow_handle_dv *dv_h;
   16105                 :            :         struct mlx5_flow *dev_flow;
   16106                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16107                 :            :         uint32_t handle_idx;
   16108                 :            :         int n;
   16109                 :            :         int err;
   16110                 :            :         int idx;
   16111                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   16112                 :          0 :         struct mlx5_flow_rss_desc *rss_desc = &wks->rss_desc;
   16113                 :            :         uint8_t misc_mask;
   16114                 :            : 
   16115                 :            :         MLX5_ASSERT(wks);
   16116         [ #  # ]:          0 :         for (idx = wks->flow_idx - 1; idx >= 0; idx--) {
   16117                 :          0 :                 dev_flow = &wks->flows[idx];
   16118                 :            :                 dv = &dev_flow->dv;
   16119                 :          0 :                 dh = dev_flow->handle;
   16120                 :            :                 dv_h = &dh->dvh;
   16121                 :          0 :                 n = dv->actions_n;
   16122         [ #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_DROP) {
   16123         [ #  # ]:          0 :                         if (dv->transfer) {
   16124                 :            :                                 MLX5_ASSERT(priv->sh->dr_drop_action);
   16125                 :          0 :                                 dv->actions[n++] = priv->sh->dr_drop_action;
   16126                 :            :                         } else {
   16127                 :            : #ifdef HAVE_MLX5DV_DR
   16128                 :            :                                 /* DR supports drop action placeholder. */
   16129                 :            :                                 MLX5_ASSERT(priv->sh->dr_drop_action);
   16130                 :          0 :                                 dv->actions[n++] = dv->group ?
   16131         [ #  # ]:          0 :                                         priv->sh->dr_drop_action :
   16132                 :            :                                         priv->root_drop_action;
   16133                 :            : #else
   16134                 :            :                                 /* For DV we use the explicit drop queue. */
   16135                 :            :                                 MLX5_ASSERT(priv->drop_queue.hrxq);
   16136                 :            :                                 dv->actions[n++] =
   16137                 :            :                                                 priv->drop_queue.hrxq->action;
   16138                 :            : #endif
   16139                 :            :                         }
   16140         [ #  # ]:          0 :                 } else if ((dh->fate_action == MLX5_FLOW_FATE_QUEUE &&
   16141   [ #  #  #  # ]:          0 :                            !dv_h->rix_sample && !dv_h->rix_dest_array)) {
   16142                 :            :                         struct mlx5_hrxq *hrxq;
   16143                 :            :                         uint32_t hrxq_idx;
   16144                 :            : 
   16145                 :          0 :                         hrxq = flow_dv_hrxq_prepare(dev, dev_flow, rss_desc,
   16146                 :            :                                                     &hrxq_idx);
   16147         [ #  # ]:          0 :                         if (!hrxq) {
   16148                 :          0 :                                 rte_flow_error_set
   16149                 :            :                                         (error, rte_errno,
   16150                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16151                 :            :                                          "cannot get hash queue");
   16152                 :          0 :                                 goto error;
   16153                 :            :                         }
   16154                 :          0 :                         dh->rix_hrxq = hrxq_idx;
   16155                 :          0 :                         dv->actions[n++] = hrxq->action;
   16156         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
   16157                 :            :                         struct mlx5_hrxq *hrxq = NULL;
   16158                 :            :                         uint32_t hrxq_idx;
   16159                 :            : 
   16160                 :          0 :                         hrxq_idx = mlx5_flow_dv_action_rss_hrxq_lookup(dev,
   16161                 :            :                                                                        rss_desc->shared_rss,
   16162                 :            :                                                                        dev_flow->hash_fields);
   16163         [ #  # ]:          0 :                         if (hrxq_idx)
   16164                 :          0 :                                 hrxq = mlx5_ipool_get
   16165                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_HRXQ],
   16166                 :            :                                          hrxq_idx);
   16167         [ #  # ]:          0 :                         if (!hrxq) {
   16168                 :          0 :                                 rte_flow_error_set
   16169                 :            :                                         (error, rte_errno,
   16170                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16171                 :            :                                          "cannot get hash queue");
   16172                 :          0 :                                 goto error;
   16173                 :            :                         }
   16174                 :          0 :                         dh->rix_srss = rss_desc->shared_rss;
   16175                 :          0 :                         dv->actions[n++] = hrxq->action;
   16176         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_DEFAULT_MISS) {
   16177         [ #  # ]:          0 :                         if (!priv->sh->default_miss_action) {
   16178                 :          0 :                                 rte_flow_error_set
   16179                 :            :                                         (error, rte_errno,
   16180                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16181                 :            :                                          "default miss action not be created.");
   16182                 :          0 :                                 goto error;
   16183                 :            :                         }
   16184                 :          0 :                         dv->actions[n++] = priv->sh->default_miss_action;
   16185                 :            :                 }
   16186         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(dv_h->matcher->mask.buf);
   16187                 :            :                 __flow_dv_adjust_buf_size(&dv->value.size, misc_mask);
   16188                 :          0 :                 err = mlx5_flow_os_create_flow(dv_h->matcher->matcher_object,
   16189                 :          0 :                                                (void *)&dv->value, n,
   16190                 :          0 :                                                dv->actions, &dh->drv_flow);
   16191                 :            :                 if (err) {
   16192                 :          0 :                         rte_flow_error_set
   16193                 :          0 :                                 (error, errno,
   16194                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   16195                 :            :                                 NULL,
   16196         [ #  # ]:          0 :                                 (!priv->sh->config.allow_duplicate_pattern &&
   16197         [ #  # ]:          0 :                                 errno == EEXIST) ?
   16198                 :            :                                 "duplicating pattern is not allowed" :
   16199                 :            :                                 "hardware refuses to create flow");
   16200                 :          0 :                         goto error;
   16201                 :            :                 }
   16202         [ #  # ]:          0 :                 if (priv->vmwa_context &&
   16203   [ #  #  #  # ]:          0 :                     dh->vf_vlan.tag && !dh->vf_vlan.created) {
   16204                 :            :                         /*
   16205                 :            :                          * The rule contains the VLAN pattern.
   16206                 :            :                          * For VF we are going to create VLAN
   16207                 :            :                          * interface to make hypervisor set correct
   16208                 :            :                          * e-Switch vport context.
   16209                 :            :                          */
   16210                 :          0 :                         mlx5_vlan_vmwa_acquire(dev, &dh->vf_vlan);
   16211                 :            :                 }
   16212                 :            :         }
   16213                 :            :         return 0;
   16214                 :          0 : error:
   16215                 :          0 :         err = rte_errno; /* Save rte_errno before cleanup. */
   16216   [ #  #  #  #  :          0 :         SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
                   #  # ]
   16217                 :            :                        handle_idx, dh, next) {
   16218                 :            :                 /* hrxq is union, don't clear it if the flag is not set. */
   16219   [ #  #  #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE && dh->rix_hrxq &&
   16220   [ #  #  #  # ]:          0 :                     !dh->dvh.rix_sample && !dh->dvh.rix_dest_array) {
   16221                 :          0 :                         mlx5_hrxq_release(dev, dh->rix_hrxq);
   16222                 :          0 :                         dh->rix_hrxq = 0;
   16223         [ #  # ]:          0 :                 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) {
   16224                 :          0 :                         dh->rix_srss = 0;
   16225                 :            :                 }
   16226   [ #  #  #  # ]:          0 :                 if (dh->vf_vlan.tag && dh->vf_vlan.created)
   16227                 :          0 :                         mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
   16228                 :            :         }
   16229                 :          0 :         rte_errno = err; /* Restore rte_errno. */
   16230                 :          0 :         return -rte_errno;
   16231                 :            : }
   16232                 :            : 
   16233                 :            : void
   16234                 :          0 : mlx5_flow_matcher_remove_cb(void *tool_ctx __rte_unused,
   16235                 :            :                             struct mlx5_list_entry *entry)
   16236                 :            : {
   16237                 :            :         struct mlx5_flow_dv_matcher *resource = container_of(entry,
   16238                 :            :                                                              typeof(*resource),
   16239                 :            :                                                              entry);
   16240                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16241                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16242                 :            : 
   16243         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16244                 :          0 :                 claim_zero(mlx5dr_bwc_matcher_destroy((struct mlx5dr_bwc_matcher *)
   16245                 :            :                                                                 resource->matcher_object));
   16246                 :            :         else
   16247                 :            : #endif
   16248                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(resource->matcher_object));
   16249                 :          0 :         mlx5_free(resource);
   16250                 :          0 : }
   16251                 :            : 
   16252                 :            : /**
   16253                 :            :  * Release the flow matcher.
   16254                 :            :  *
   16255                 :            :  * @param dev
   16256                 :            :  *   Pointer to Ethernet device.
   16257                 :            :  * @param port_id
   16258                 :            :  *   Index to port ID action resource.
   16259                 :            :  *
   16260                 :            :  * @return
   16261                 :            :  *   1 while a reference on it exists, 0 when freed.
   16262                 :            :  */
   16263                 :            : static int
   16264                 :          0 : flow_dv_matcher_release(struct rte_eth_dev *dev,
   16265                 :            :                         struct mlx5_flow_handle *handle)
   16266                 :            : {
   16267                 :          0 :         struct mlx5_flow_dv_matcher *matcher = handle->dvh.matcher;
   16268                 :          0 :         struct mlx5_flow_tbl_data_entry *tbl = container_of(matcher->tbl,
   16269                 :            :                                                             typeof(*tbl), tbl);
   16270                 :            :         int ret;
   16271                 :            : 
   16272                 :            :         MLX5_ASSERT(matcher->matcher_object);
   16273                 :          0 :         ret = mlx5_list_unregister(tbl->matchers, &matcher->entry);
   16274                 :          0 :         mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl->tbl);
   16275                 :          0 :         return ret;
   16276                 :            : }
   16277                 :            : 
   16278                 :            : void
   16279                 :          0 : mlx5_flow_encap_decap_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16280                 :            : {
   16281                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16282                 :            :         struct mlx5_flow_dv_encap_decap_resource *res =
   16283                 :            :                                        container_of(entry, typeof(*res), entry);
   16284                 :            : 
   16285                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16286         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16287                 :          0 :                 claim_zero(mlx5dr_action_destroy(res->action));
   16288                 :            :         else
   16289                 :            : #endif
   16290                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
   16291                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx);
   16292                 :          0 : }
   16293                 :            : 
   16294                 :            : /**
   16295                 :            :  * Release an encap/decap resource.
   16296                 :            :  *
   16297                 :            :  * @param dev
   16298                 :            :  *   Pointer to Ethernet device.
   16299                 :            :  * @param encap_decap_idx
   16300                 :            :  *   Index of encap decap resource.
   16301                 :            :  *
   16302                 :            :  * @return
   16303                 :            :  *   1 while a reference on it exists, 0 when freed.
   16304                 :            :  */
   16305                 :            : int
   16306                 :          0 : mlx5_flow_encap_decap_resource_release(struct rte_eth_dev *dev,
   16307                 :            :                                        uint32_t encap_decap_idx)
   16308                 :            : {
   16309                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16310                 :            :         struct mlx5_flow_dv_encap_decap_resource *resource;
   16311                 :            : 
   16312                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
   16313                 :            :                                   encap_decap_idx);
   16314         [ #  # ]:          0 :         if (!resource)
   16315                 :            :                 return 0;
   16316                 :            :         MLX5_ASSERT(resource->action);
   16317                 :          0 :         return mlx5_hlist_unregister(priv->sh->encaps_decaps, &resource->entry);
   16318                 :            : }
   16319                 :            : 
   16320                 :            : /**
   16321                 :            :  * Release an jump to table action resource.
   16322                 :            :  *
   16323                 :            :  * @param dev
   16324                 :            :  *   Pointer to Ethernet device.
   16325                 :            :  * @param rix_jump
   16326                 :            :  *   Index to the jump action resource.
   16327                 :            :  *
   16328                 :            :  * @return
   16329                 :            :  *   1 while a reference on it exists, 0 when freed.
   16330                 :            :  */
   16331                 :            : static int
   16332                 :          0 : flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
   16333                 :            :                                   uint32_t rix_jump)
   16334                 :            : {
   16335                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16336                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   16337                 :            : 
   16338                 :          0 :         tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP],
   16339                 :            :                                   rix_jump);
   16340         [ #  # ]:          0 :         if (!tbl_data)
   16341                 :            :                 return 0;
   16342                 :          0 :         return mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl_data->tbl);
   16343                 :            : }
   16344                 :            : 
   16345                 :            : void
   16346                 :          0 : mlx5_flow_modify_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16347                 :            : {
   16348                 :            :         struct mlx5_flow_dv_modify_hdr_resource *res =
   16349                 :            :                 container_of(entry, typeof(*res), entry);
   16350                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16351                 :            : 
   16352                 :            : #ifdef HAVE_MLX5_HWS_SUPPORT
   16353         [ #  # ]:          0 :         if (sh->config.dv_flow_en == 2)
   16354                 :          0 :                 claim_zero(mlx5dr_action_destroy(res->action));
   16355                 :            :         else
   16356                 :            : #endif
   16357                 :          0 :                 claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
   16358                 :          0 :         mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
   16359                 :          0 : }
   16360                 :            : 
   16361                 :            : /**
   16362                 :            :  * Release a modify-header resource.
   16363                 :            :  *
   16364                 :            :  * @param dev
   16365                 :            :  *   Pointer to Ethernet device.
   16366                 :            :  * @param handle
   16367                 :            :  *   Pointer to mlx5_flow_handle.
   16368                 :            :  *
   16369                 :            :  * @return
   16370                 :            :  *   1 while a reference on it exists, 0 when freed.
   16371                 :            :  */
   16372                 :            : static int
   16373                 :            : flow_dv_modify_hdr_resource_release(struct rte_eth_dev *dev,
   16374                 :            :                                     struct mlx5_flow_handle *handle)
   16375                 :            : {
   16376                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16377                 :            :         struct mlx5_flow_dv_modify_hdr_resource *entry = handle->dvh.modify_hdr;
   16378                 :            : 
   16379                 :            :         MLX5_ASSERT(entry->action);
   16380                 :          0 :         return mlx5_hlist_unregister(priv->sh->modify_cmds, &entry->entry);
   16381                 :            : }
   16382                 :            : 
   16383                 :            : void
   16384                 :          0 : mlx5_flow_dv_port_id_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16385                 :            : {
   16386                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16387                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource =
   16388                 :            :                                   container_of(entry, typeof(*resource), entry);
   16389                 :            : 
   16390                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16391                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], resource->idx);
   16392                 :          0 : }
   16393                 :            : 
   16394                 :            : /**
   16395                 :            :  * Release port ID action resource.
   16396                 :            :  *
   16397                 :            :  * @param dev
   16398                 :            :  *   Pointer to Ethernet device.
   16399                 :            :  * @param handle
   16400                 :            :  *   Pointer to mlx5_flow_handle.
   16401                 :            :  *
   16402                 :            :  * @return
   16403                 :            :  *   1 while a reference on it exists, 0 when freed.
   16404                 :            :  */
   16405                 :            : static int
   16406                 :          0 : flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
   16407                 :            :                                         uint32_t port_id)
   16408                 :            : {
   16409                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16410                 :            :         struct mlx5_flow_dv_port_id_action_resource *resource;
   16411                 :            : 
   16412                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID], port_id);
   16413         [ #  # ]:          0 :         if (!resource)
   16414                 :            :                 return 0;
   16415                 :            :         MLX5_ASSERT(resource->action);
   16416                 :          0 :         return mlx5_list_unregister(priv->sh->port_id_action_list,
   16417                 :            :                                     &resource->entry);
   16418                 :            : }
   16419                 :            : 
   16420                 :            : /**
   16421                 :            :  * Release shared RSS action resource.
   16422                 :            :  *
   16423                 :            :  * @param dev
   16424                 :            :  *   Pointer to Ethernet device.
   16425                 :            :  * @param srss
   16426                 :            :  *   Shared RSS action index.
   16427                 :            :  */
   16428                 :            : static void
   16429                 :          0 : flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss)
   16430                 :            : {
   16431                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16432                 :            :         struct mlx5_shared_action_rss *shared_rss;
   16433                 :            : 
   16434                 :          0 :         shared_rss = mlx5_ipool_get
   16435                 :          0 :                         (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], srss);
   16436                 :          0 :         rte_atomic_fetch_sub_explicit(&shared_rss->refcnt, 1, rte_memory_order_relaxed);
   16437                 :          0 : }
   16438                 :            : 
   16439                 :            : void
   16440                 :          0 : mlx5_flow_dv_push_vlan_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
   16441                 :            : {
   16442                 :            :         struct mlx5_dev_ctx_shared *sh = tool_ctx;
   16443                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource =
   16444                 :            :                         container_of(entry, typeof(*resource), entry);
   16445                 :            : 
   16446                 :          0 :         claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16447                 :          0 :         mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], resource->idx);
   16448                 :          0 : }
   16449                 :            : 
   16450                 :            : /**
   16451                 :            :  * Release push vlan action resource.
   16452                 :            :  *
   16453                 :            :  * @param dev
   16454                 :            :  *   Pointer to Ethernet device.
   16455                 :            :  * @param handle
   16456                 :            :  *   Pointer to mlx5_flow_handle.
   16457                 :            :  *
   16458                 :            :  * @return
   16459                 :            :  *   1 while a reference on it exists, 0 when freed.
   16460                 :            :  */
   16461                 :            : static int
   16462                 :          0 : flow_dv_push_vlan_action_resource_release(struct rte_eth_dev *dev,
   16463                 :            :                                           struct mlx5_flow_handle *handle)
   16464                 :            : {
   16465                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16466                 :            :         struct mlx5_flow_dv_push_vlan_action_resource *resource;
   16467                 :          0 :         uint32_t idx = handle->dvh.rix_push_vlan;
   16468                 :            : 
   16469                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx);
   16470         [ #  # ]:          0 :         if (!resource)
   16471                 :            :                 return 0;
   16472                 :            :         MLX5_ASSERT(resource->action);
   16473                 :          0 :         return mlx5_list_unregister(priv->sh->push_vlan_action_list,
   16474                 :            :                                     &resource->entry);
   16475                 :            : }
   16476                 :            : 
   16477                 :            : /**
   16478                 :            :  * Release the fate resource.
   16479                 :            :  *
   16480                 :            :  * @param dev
   16481                 :            :  *   Pointer to Ethernet device.
   16482                 :            :  * @param handle
   16483                 :            :  *   Pointer to mlx5_flow_handle.
   16484                 :            :  */
   16485                 :            : static void
   16486                 :          0 : flow_dv_fate_resource_release(struct rte_eth_dev *dev,
   16487                 :            :                                struct mlx5_flow_handle *handle)
   16488                 :            : {
   16489         [ #  # ]:          0 :         if (!handle->rix_fate)
   16490                 :            :                 return;
   16491   [ #  #  #  #  :          0 :         switch (handle->fate_action) {
                      # ]
   16492                 :          0 :         case MLX5_FLOW_FATE_QUEUE:
   16493   [ #  #  #  # ]:          0 :                 if (!handle->dvh.rix_sample && !handle->dvh.rix_dest_array)
   16494                 :          0 :                         mlx5_hrxq_release(dev, handle->rix_hrxq);
   16495                 :            :                 break;
   16496                 :          0 :         case MLX5_FLOW_FATE_JUMP:
   16497                 :          0 :                 flow_dv_jump_tbl_resource_release(dev, handle->rix_jump);
   16498                 :          0 :                 break;
   16499                 :          0 :         case MLX5_FLOW_FATE_PORT_ID:
   16500                 :          0 :                 flow_dv_port_id_action_resource_release(dev, handle->rix_port_id_action);
   16501                 :          0 :                 break;
   16502                 :            :         case MLX5_FLOW_FATE_SEND_TO_KERNEL:
   16503                 :            :                 /* In case of send_to_kernel action the actual release of
   16504                 :            :                  * resource is done when all shared DR resources are released
   16505                 :            :                  * since this resource is created once and always reused.
   16506                 :            :                  */
   16507                 :            :                 break;
   16508                 :          0 :         default:
   16509                 :          0 :                 DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action);
   16510                 :          0 :                 break;
   16511                 :            :         }
   16512                 :          0 :         handle->rix_fate = 0;
   16513                 :            : }
   16514                 :            : 
   16515                 :            : void
   16516                 :          0 : mlx5_flow_dv_sample_remove_cb(void *tool_ctx __rte_unused,
   16517                 :            :                          struct mlx5_list_entry *entry)
   16518                 :            : {
   16519                 :            :         struct mlx5_flow_dv_sample_resource *resource = container_of(entry,
   16520                 :            :                                                               typeof(*resource),
   16521                 :            :                                                               entry);
   16522                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   16523                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16524                 :            : 
   16525         [ #  # ]:          0 :         if (resource->verbs_action)
   16526                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action
   16527                 :            :                                                       (resource->verbs_action));
   16528         [ #  # ]:          0 :         if (resource->normal_path_tbl)
   16529                 :          0 :                 mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), resource->normal_path_tbl);
   16530                 :          0 :         flow_dv_sample_sub_actions_release(dev, &resource->sample_idx);
   16531                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], resource->idx);
   16532                 :          0 :         DRV_LOG(DEBUG, "sample resource %p: removed", (void *)resource);
   16533                 :          0 : }
   16534                 :            : 
   16535                 :            : /**
   16536                 :            :  * Release an sample resource.
   16537                 :            :  *
   16538                 :            :  * @param dev
   16539                 :            :  *   Pointer to Ethernet device.
   16540                 :            :  * @param handle
   16541                 :            :  *   Pointer to mlx5_flow_handle.
   16542                 :            :  *
   16543                 :            :  * @return
   16544                 :            :  *   1 while a reference on it exists, 0 when freed.
   16545                 :            :  */
   16546                 :            : static int
   16547                 :          0 : flow_dv_sample_resource_release(struct rte_eth_dev *dev,
   16548                 :            :                                      struct mlx5_flow_handle *handle)
   16549                 :            : {
   16550                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16551                 :            :         struct mlx5_flow_dv_sample_resource *resource;
   16552                 :            : 
   16553                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_SAMPLE],
   16554                 :            :                                   handle->dvh.rix_sample);
   16555         [ #  # ]:          0 :         if (!resource)
   16556                 :            :                 return 0;
   16557                 :            :         MLX5_ASSERT(resource->verbs_action);
   16558                 :          0 :         return mlx5_list_unregister(priv->sh->sample_action_list,
   16559                 :            :                                     &resource->entry);
   16560                 :            : }
   16561                 :            : 
   16562                 :            : void
   16563                 :          0 : mlx5_flow_dv_dest_array_remove_cb(void *tool_ctx __rte_unused,
   16564                 :            :                              struct mlx5_list_entry *entry)
   16565                 :            : {
   16566                 :            :         struct mlx5_flow_dv_dest_array_resource *resource =
   16567                 :            :                         container_of(entry, typeof(*resource), entry);
   16568                 :          0 :         struct rte_eth_dev *dev = resource->dev;
   16569                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16570                 :            :         uint32_t i = 0;
   16571                 :            : 
   16572                 :            :         MLX5_ASSERT(resource->action);
   16573         [ #  # ]:          0 :         if (resource->action)
   16574                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action(resource->action));
   16575         [ #  # ]:          0 :         for (; i < resource->num_of_dest; i++)
   16576                 :          0 :                 flow_dv_sample_sub_actions_release(dev,
   16577                 :            :                                                    &resource->sample_idx[i]);
   16578                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], resource->idx);
   16579                 :          0 :         DRV_LOG(DEBUG, "destination array resource %p: removed",
   16580                 :            :                 (void *)resource);
   16581                 :          0 : }
   16582                 :            : 
   16583                 :            : /**
   16584                 :            :  * Release an destination array resource.
   16585                 :            :  *
   16586                 :            :  * @param dev
   16587                 :            :  *   Pointer to Ethernet device.
   16588                 :            :  * @param handle
   16589                 :            :  *   Pointer to mlx5_flow_handle.
   16590                 :            :  *
   16591                 :            :  * @return
   16592                 :            :  *   1 while a reference on it exists, 0 when freed.
   16593                 :            :  */
   16594                 :            : static int
   16595                 :          0 : flow_dv_dest_array_resource_release(struct rte_eth_dev *dev,
   16596                 :            :                                     struct mlx5_flow_handle *handle)
   16597                 :            : {
   16598                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16599                 :            :         struct mlx5_flow_dv_dest_array_resource *resource;
   16600                 :            : 
   16601                 :          0 :         resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],
   16602                 :            :                                   handle->dvh.rix_dest_array);
   16603         [ #  # ]:          0 :         if (!resource)
   16604                 :            :                 return 0;
   16605                 :            :         MLX5_ASSERT(resource->action);
   16606                 :          0 :         return mlx5_list_unregister(priv->sh->dest_array_list,
   16607                 :            :                                     &resource->entry);
   16608                 :            : }
   16609                 :            : 
   16610                 :            : static void
   16611                 :          0 : flow_dev_geneve_tlv_option_resource_release(struct mlx5_dev_ctx_shared *sh)
   16612                 :            : {
   16613                 :          0 :         struct mlx5_geneve_tlv_option_resource *geneve_opt_resource =
   16614                 :            :                                 sh->geneve_tlv_option_resource;
   16615                 :          0 :         rte_spinlock_lock(&sh->geneve_tlv_opt_sl);
   16616         [ #  # ]:          0 :         if (geneve_opt_resource) {
   16617         [ #  # ]:          0 :                 if (!(rte_atomic_fetch_sub_explicit(&geneve_opt_resource->refcnt, 1,
   16618                 :            :                                          rte_memory_order_relaxed) - 1)) {
   16619                 :          0 :                         claim_zero(mlx5_devx_cmd_destroy
   16620                 :            :                                         (geneve_opt_resource->obj));
   16621                 :          0 :                         mlx5_free(sh->geneve_tlv_option_resource);
   16622                 :          0 :                         sh->geneve_tlv_option_resource = NULL;
   16623                 :            :                 }
   16624                 :            :         }
   16625                 :            :         rte_spinlock_unlock(&sh->geneve_tlv_opt_sl);
   16626                 :          0 : }
   16627                 :            : 
   16628                 :            : /**
   16629                 :            :  * Remove the flow from the NIC but keeps it in memory.
   16630                 :            :  * Lock free, (mutex should be acquired by caller).
   16631                 :            :  *
   16632                 :            :  * @param[in] dev
   16633                 :            :  *   Pointer to Ethernet device.
   16634                 :            :  * @param[in, out] flow
   16635                 :            :  *   Pointer to flow structure.
   16636                 :            :  */
   16637                 :            : static void
   16638                 :          0 : flow_dv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
   16639                 :            : {
   16640                 :            :         struct mlx5_flow_handle *dh;
   16641                 :            :         uint32_t handle_idx;
   16642                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16643                 :            : 
   16644         [ #  # ]:          0 :         if (!flow)
   16645                 :            :                 return;
   16646                 :          0 :         handle_idx = flow->dev_handles;
   16647         [ #  # ]:          0 :         while (handle_idx) {
   16648                 :          0 :                 dh = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   16649                 :            :                                     handle_idx);
   16650         [ #  # ]:          0 :                 if (!dh)
   16651                 :            :                         return;
   16652         [ #  # ]:          0 :                 if (dh->drv_flow) {
   16653                 :            :                         claim_zero(mlx5_flow_os_destroy_flow(dh->drv_flow));
   16654                 :          0 :                         dh->drv_flow = NULL;
   16655                 :            :                 }
   16656         [ #  # ]:          0 :                 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE)
   16657                 :          0 :                         flow_dv_fate_resource_release(dev, dh);
   16658   [ #  #  #  # ]:          0 :                 if (dh->vf_vlan.tag && dh->vf_vlan.created)
   16659                 :          0 :                         mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
   16660                 :          0 :                 handle_idx = dh->next.next;
   16661                 :            :         }
   16662                 :            : }
   16663                 :            : 
   16664                 :            : /**
   16665                 :            :  * Remove the flow from the NIC and the memory.
   16666                 :            :  * Lock free, (mutex should be acquired by caller).
   16667                 :            :  *
   16668                 :            :  * @param[in] dev
   16669                 :            :  *   Pointer to the Ethernet device structure.
   16670                 :            :  * @param[in, out] flow
   16671                 :            :  *   Pointer to flow structure.
   16672                 :            :  */
   16673                 :            : static void
   16674                 :          0 : flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
   16675                 :            : {
   16676                 :            :         struct mlx5_flow_handle *dev_handle;
   16677                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16678                 :            :         struct mlx5_flow_meter_info *fm = NULL;
   16679                 :            :         uint32_t srss = 0;
   16680                 :            : 
   16681         [ #  # ]:          0 :         if (!flow)
   16682                 :            :                 return;
   16683                 :          0 :         flow_dv_remove(dev, flow);
   16684         [ #  # ]:          0 :         if (flow->counter) {
   16685                 :          0 :                 flow_dv_counter_free(dev, flow->counter);
   16686                 :          0 :                 flow->counter = 0;
   16687                 :            :         }
   16688         [ #  # ]:          0 :         if (flow->meter) {
   16689                 :          0 :                 fm = mlx5_flow_dv_meter_find_by_idx(priv, flow->meter);
   16690         [ #  # ]:          0 :                 if (fm)
   16691                 :          0 :                         mlx5_flow_meter_detach(priv, fm);
   16692                 :          0 :                 flow->meter = 0;
   16693                 :            :         }
   16694                 :            :         /* Keep the current age handling by default. */
   16695   [ #  #  #  # ]:          0 :         if (flow->indirect_type == MLX5_INDIRECT_ACTION_TYPE_CT && flow->ct)
   16696                 :          0 :                 flow_dv_aso_ct_release(dev, flow->ct, NULL);
   16697         [ #  # ]:          0 :         else if (flow->age)
   16698                 :          0 :                 flow_dv_aso_age_release(dev, flow->age);
   16699         [ #  # ]:          0 :         while (flow->geneve_tlv_option) {
   16700                 :          0 :                 flow_dev_geneve_tlv_option_resource_release(priv->sh);
   16701                 :          0 :                 flow->geneve_tlv_option--;
   16702                 :            :         }
   16703         [ #  # ]:          0 :         while (flow->dev_handles) {
   16704                 :            :                 uint32_t tmp_idx = flow->dev_handles;
   16705                 :            : 
   16706                 :          0 :                 dev_handle = mlx5_ipool_get(priv->sh->ipool
   16707                 :            :                                             [MLX5_IPOOL_MLX5_FLOW], tmp_idx);
   16708         [ #  # ]:          0 :                 if (!dev_handle)
   16709                 :            :                         return;
   16710                 :          0 :                 flow->dev_handles = dev_handle->next.next;
   16711         [ #  # ]:          0 :                 while (dev_handle->flex_item) {
   16712                 :          0 :                         int index = rte_bsf32(dev_handle->flex_item);
   16713                 :            : 
   16714                 :          0 :                         mlx5_flex_release_index(dev, index);
   16715                 :          0 :                         dev_handle->flex_item &= ~(uint8_t)RTE_BIT32(index);
   16716                 :            :                 }
   16717         [ #  # ]:          0 :                 if (dev_handle->dvh.matcher)
   16718                 :          0 :                         flow_dv_matcher_release(dev, dev_handle);
   16719         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_sample)
   16720                 :          0 :                         flow_dv_sample_resource_release(dev, dev_handle);
   16721         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_dest_array)
   16722                 :          0 :                         flow_dv_dest_array_resource_release(dev, dev_handle);
   16723         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_encap_decap)
   16724                 :          0 :                         mlx5_flow_encap_decap_resource_release(dev,
   16725                 :            :                                                                dev_handle->dvh.rix_encap_decap);
   16726         [ #  # ]:          0 :                 if (dev_handle->dvh.modify_hdr)
   16727                 :            :                         flow_dv_modify_hdr_resource_release(dev, dev_handle);
   16728         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_push_vlan)
   16729                 :          0 :                         flow_dv_push_vlan_action_resource_release(dev,
   16730                 :            :                                                                   dev_handle);
   16731         [ #  # ]:          0 :                 if (dev_handle->dvh.rix_tag)
   16732                 :          0 :                         flow_dv_tag_release(dev,
   16733                 :            :                                             dev_handle->dvh.rix_tag);
   16734         [ #  # ]:          0 :                 if (dev_handle->fate_action != MLX5_FLOW_FATE_SHARED_RSS)
   16735                 :          0 :                         flow_dv_fate_resource_release(dev, dev_handle);
   16736         [ #  # ]:          0 :                 else if (!srss)
   16737                 :          0 :                         srss = dev_handle->rix_srss;
   16738   [ #  #  #  # ]:          0 :                 if (fm && dev_handle->is_meter_flow_id &&
   16739         [ #  # ]:          0 :                     dev_handle->split_flow_id)
   16740                 :          0 :                         mlx5_ipool_free(fm->flow_ipool,
   16741                 :            :                                         dev_handle->split_flow_id);
   16742         [ #  # ]:          0 :                 else if (dev_handle->split_flow_id &&
   16743         [ #  # ]:          0 :                     !dev_handle->is_meter_flow_id)
   16744                 :          0 :                         mlx5_ipool_free(priv->sh->ipool
   16745                 :            :                                         [MLX5_IPOOL_RSS_EXPANTION_FLOW_ID],
   16746                 :            :                                         dev_handle->split_flow_id);
   16747                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
   16748                 :            :                            tmp_idx);
   16749                 :            :         }
   16750         [ #  # ]:          0 :         if (srss)
   16751                 :          0 :                 flow_dv_shared_rss_action_release(dev, srss);
   16752                 :            : }
   16753                 :            : 
   16754                 :            : /**
   16755                 :            :  * Release array of hash RX queue objects.
   16756                 :            :  * Helper function.
   16757                 :            :  *
   16758                 :            :  * @param[in] dev
   16759                 :            :  *   Pointer to the Ethernet device structure.
   16760                 :            :  * @param[in, out] hrxqs
   16761                 :            :  *   Array of hash RX queue objects.
   16762                 :            :  *
   16763                 :            :  * @return
   16764                 :            :  *   Total number of references to hash RX queue objects in *hrxqs* array
   16765                 :            :  *   after this operation.
   16766                 :            :  */
   16767                 :            : static int
   16768                 :          0 : __flow_dv_hrxqs_release(struct rte_eth_dev *dev,
   16769                 :            :                         uint32_t (*hrxqs)[MLX5_RSS_HASH_IDX_MAX])
   16770                 :            : {
   16771                 :            :         size_t i;
   16772                 :            :         int remaining = 0;
   16773                 :            : 
   16774         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(*hrxqs); i++) {
   16775                 :          0 :                 int ret = mlx5_hrxq_release(dev, (*hrxqs)[i]);
   16776                 :            : 
   16777         [ #  # ]:          0 :                 if (!ret)
   16778                 :          0 :                         (*hrxqs)[i] = 0;
   16779                 :          0 :                 remaining += ret;
   16780                 :            :         }
   16781                 :          0 :         return remaining;
   16782                 :            : }
   16783                 :            : 
   16784                 :            : /**
   16785                 :            :  * Release all hash RX queue objects representing shared RSS action.
   16786                 :            :  *
   16787                 :            :  * @param[in] dev
   16788                 :            :  *   Pointer to the Ethernet device structure.
   16789                 :            :  * @param[in, out] action
   16790                 :            :  *   Shared RSS action to remove hash RX queue objects from.
   16791                 :            :  *
   16792                 :            :  * @return
   16793                 :            :  *   Total number of references to hash RX queue objects stored in *action*
   16794                 :            :  *   after this operation.
   16795                 :            :  *   Expected to be 0 if no external references held.
   16796                 :            :  */
   16797                 :            : static int
   16798                 :            : __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev,
   16799                 :            :                                  struct mlx5_shared_action_rss *shared_rss)
   16800                 :            : {
   16801                 :          0 :         return __flow_dv_hrxqs_release(dev, &shared_rss->hrxq);
   16802                 :            : }
   16803                 :            : 
   16804                 :            : static inline void
   16805                 :            : filter_ipv4_types(uint64_t rss_types, uint64_t *hash_fields)
   16806                 :            : {
   16807         [ #  # ]:          0 :         if (rss_types & MLX5_IPV4_LAYER_TYPES) {
   16808                 :          0 :                 *hash_fields &= ~MLX5_RSS_HASH_IPV4;
   16809         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   16810                 :          0 :                         *hash_fields |= IBV_RX_HASH_DST_IPV4;
   16811         [ #  # ]:          0 :                 else if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   16812                 :          0 :                         *hash_fields |= IBV_RX_HASH_SRC_IPV4;
   16813                 :            :                 else
   16814                 :          0 :                         *hash_fields |= MLX5_RSS_HASH_IPV4;
   16815                 :            :         }
   16816                 :            : }
   16817                 :            : 
   16818                 :            : static inline void
   16819                 :            : filter_ipv6_types(uint64_t rss_types, uint64_t *hash_fields)
   16820                 :            : {
   16821         [ #  # ]:          0 :         if (rss_types & MLX5_IPV6_LAYER_TYPES) {
   16822                 :          0 :                 *hash_fields &= ~MLX5_RSS_HASH_IPV6;
   16823         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_L3_DST_ONLY)
   16824                 :          0 :                         *hash_fields |= IBV_RX_HASH_DST_IPV6;
   16825         [ #  # ]:          0 :                 else if (rss_types & RTE_ETH_RSS_L3_SRC_ONLY)
   16826                 :          0 :                         *hash_fields |= IBV_RX_HASH_SRC_IPV6;
   16827                 :            :                 else
   16828                 :          0 :                         *hash_fields |= MLX5_RSS_HASH_IPV6;
   16829                 :            :         }
   16830                 :            : }
   16831                 :            : 
   16832                 :            : static inline void
   16833                 :            : filter_udp_types(uint64_t rss_types, uint64_t *hash_fields)
   16834                 :            : {
   16835         [ #  # ]:          0 :         if (rss_types & RTE_ETH_RSS_UDP) {
   16836                 :          0 :                 *hash_fields &= ~MLX5_UDP_IBV_RX_HASH;
   16837         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   16838                 :          0 :                         *hash_fields |= IBV_RX_HASH_DST_PORT_UDP;
   16839         [ #  # ]:          0 :                 else if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   16840                 :          0 :                         *hash_fields |= IBV_RX_HASH_SRC_PORT_UDP;
   16841                 :            :                 else
   16842                 :          0 :                         *hash_fields |= MLX5_UDP_IBV_RX_HASH;
   16843                 :            :         }
   16844                 :            : }
   16845                 :            : 
   16846                 :            : static inline void
   16847                 :            : filter_tcp_types(uint64_t rss_types, uint64_t *hash_fields)
   16848                 :            : {
   16849         [ #  # ]:          0 :         if (rss_types & RTE_ETH_RSS_TCP) {
   16850                 :          0 :                 *hash_fields &= ~MLX5_TCP_IBV_RX_HASH;
   16851         [ #  # ]:          0 :                 if (rss_types & RTE_ETH_RSS_L4_DST_ONLY)
   16852                 :          0 :                         *hash_fields |= IBV_RX_HASH_DST_PORT_TCP;
   16853         [ #  # ]:          0 :                 else if (rss_types & RTE_ETH_RSS_L4_SRC_ONLY)
   16854                 :          0 :                         *hash_fields |= IBV_RX_HASH_SRC_PORT_TCP;
   16855                 :            :                 else
   16856                 :          0 :                         *hash_fields |= MLX5_TCP_IBV_RX_HASH;
   16857                 :            :         }
   16858                 :            : }
   16859                 :            : 
   16860                 :            : /**
   16861                 :            :  * Adjust L3/L4 hash value of pre-created shared RSS hrxq according to
   16862                 :            :  * user input.
   16863                 :            :  *
   16864                 :            :  * Only one hash value is available for one L3+L4 combination:
   16865                 :            :  * for example:
   16866                 :            :  * MLX5_RSS_HASH_IPV4, MLX5_RSS_HASH_IPV4_SRC_ONLY, and
   16867                 :            :  * MLX5_RSS_HASH_IPV4_DST_ONLY are mutually exclusive so they can share
   16868                 :            :  * same slot in mlx5_rss_hash_fields.
   16869                 :            :  *
   16870                 :            :  * @param[in] orig_rss_types
   16871                 :            :  *   RSS type as provided in shared RSS action, specified as a bitmap of RTE_ETH_RSS_* flags.
   16872                 :            :  * @param[in, out] hash_field
   16873                 :            :  *   hash_field variable needed to be adjusted, specified as a bitmap of #ibv_rx_hash_fields flags.
   16874                 :            :  *
   16875                 :            :  * @return
   16876                 :            :  *   void
   16877                 :            :  */
   16878                 :            : void
   16879                 :          0 : mlx5_flow_dv_action_rss_l34_hash_adjust(uint64_t orig_rss_types,
   16880                 :            :                                    uint64_t *hash_field)
   16881                 :            : {
   16882         [ #  # ]:          0 :         uint64_t hash_field_protos = *hash_field & ~IBV_RX_HASH_INNER;
   16883                 :            :         uint64_t rss_types = rte_eth_rss_hf_refine(orig_rss_types);
   16884                 :            : 
   16885         [ #  # ]:          0 :         if (hash_field_protos & MLX5_RSS_HASH_IPV4)
   16886                 :            :                 filter_ipv4_types(rss_types, hash_field);
   16887         [ #  # ]:          0 :         else if (hash_field_protos & MLX5_RSS_HASH_IPV6)
   16888                 :            :                 filter_ipv6_types(rss_types, hash_field);
   16889                 :            : 
   16890         [ #  # ]:          0 :         if (hash_field_protos & MLX5_UDP_IBV_RX_HASH)
   16891                 :            :                 filter_udp_types(rss_types, hash_field);
   16892         [ #  # ]:          0 :         else if (hash_field_protos & MLX5_TCP_IBV_RX_HASH)
   16893                 :            :                 filter_tcp_types(rss_types, hash_field);
   16894                 :          0 : }
   16895                 :            : 
   16896                 :            : /**
   16897                 :            :  * Setup shared RSS action.
   16898                 :            :  * Prepare set of hash RX queue objects sufficient to handle all valid
   16899                 :            :  * hash_fields combinations (see enum ibv_rx_hash_fields).
   16900                 :            :  *
   16901                 :            :  * @param[in] dev
   16902                 :            :  *   Pointer to the Ethernet device structure.
   16903                 :            :  * @param[in] action_idx
   16904                 :            :  *   Shared RSS action ipool index.
   16905                 :            :  * @param[in, out] action
   16906                 :            :  *   Partially initialized shared RSS action.
   16907                 :            :  * @param[out] error
   16908                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16909                 :            :  *   error only.
   16910                 :            :  *
   16911                 :            :  * @return
   16912                 :            :  *   0 on success, otherwise negative errno value.
   16913                 :            :  */
   16914                 :            : static int
   16915                 :          0 : __flow_dv_action_rss_setup(struct rte_eth_dev *dev,
   16916                 :            :                            uint32_t action_idx,
   16917                 :            :                            struct mlx5_shared_action_rss *shared_rss,
   16918                 :            :                            struct rte_flow_error *error)
   16919                 :            : {
   16920                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   16921                 :          0 :         struct mlx5_flow_rss_desc rss_desc = { 0 };
   16922                 :            :         size_t i;
   16923                 :            :         int err;
   16924                 :            : 
   16925                 :          0 :         shared_rss->ind_tbl = mlx5_ind_table_obj_new
   16926                 :            :                               (dev, shared_rss->origin.queue,
   16927                 :            :                                shared_rss->origin.queue_num,
   16928                 :            :                                true,
   16929                 :          0 :                                !!dev->data->dev_started);
   16930         [ #  # ]:          0 :         if (!shared_rss->ind_tbl)
   16931                 :          0 :                 return rte_flow_error_set(error, rte_errno,
   16932                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16933                 :            :                                           "cannot setup indirection table");
   16934                 :          0 :         memcpy(rss_desc.key, shared_rss->origin.key, MLX5_RSS_HASH_KEY_LEN);
   16935                 :          0 :         rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN;
   16936                 :          0 :         rss_desc.symmetric_hash_function =
   16937                 :          0 :                 MLX5_RSS_IS_SYMM(shared_rss->origin.func);
   16938                 :          0 :         rss_desc.const_q = shared_rss->origin.queue;
   16939                 :          0 :         rss_desc.queue_num = shared_rss->origin.queue_num;
   16940                 :            :         /* Set non-zero value to indicate a shared RSS. */
   16941                 :          0 :         rss_desc.shared_rss = action_idx;
   16942                 :          0 :         rss_desc.ind_tbl = shared_rss->ind_tbl;
   16943         [ #  # ]:          0 :         if (priv->sh->config.dv_flow_en == 2)
   16944                 :          0 :                 rss_desc.hws_flags = MLX5DR_ACTION_FLAG_HWS_RX;
   16945         [ #  # ]:          0 :         for (i = 0; i < MLX5_RSS_HASH_IDX_MAX; i++) {
   16946                 :            :                 struct mlx5_hrxq *hrxq;
   16947                 :          0 :                 uint64_t hash_fields = mlx5_rss_hash_fields[i];
   16948                 :            :                 int tunnel = 0;
   16949                 :            : 
   16950                 :          0 :                 mlx5_flow_dv_action_rss_l34_hash_adjust(shared_rss->origin.types,
   16951                 :            :                                                    &hash_fields);
   16952         [ #  # ]:          0 :                 if (shared_rss->origin.level > 1) {
   16953                 :          0 :                         hash_fields |= IBV_RX_HASH_INNER;
   16954                 :            :                         tunnel = 1;
   16955                 :            :                 }
   16956                 :          0 :                 rss_desc.tunnel = tunnel;
   16957                 :          0 :                 rss_desc.hash_fields = hash_fields;
   16958                 :          0 :                 hrxq = mlx5_hrxq_get(dev, &rss_desc);
   16959         [ #  # ]:          0 :                 if (!hrxq) {
   16960                 :          0 :                         rte_flow_error_set
   16961                 :            :                                 (error, rte_errno,
   16962                 :            :                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   16963                 :            :                                  "cannot get hash queue");
   16964                 :          0 :                         goto error_hrxq_new;
   16965                 :            :                 }
   16966                 :          0 :                 err = __flow_dv_action_rss_hrxq_set
   16967                 :            :                         (shared_rss, hash_fields, hrxq->idx);
   16968                 :            :                 MLX5_ASSERT(!err);
   16969                 :            :         }
   16970                 :            :         return 0;
   16971                 :            : error_hrxq_new:
   16972                 :          0 :         err = rte_errno;
   16973                 :            :         __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
   16974         [ #  # ]:          0 :         if (!mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true))
   16975                 :          0 :                 shared_rss->ind_tbl = NULL;
   16976                 :          0 :         rte_errno = err;
   16977                 :          0 :         return -rte_errno;
   16978                 :            : }
   16979                 :            : 
   16980                 :            : /**
   16981                 :            :  * Create shared RSS action.
   16982                 :            :  *
   16983                 :            :  * @param[in] dev
   16984                 :            :  *   Pointer to the Ethernet device structure.
   16985                 :            :  * @param[in] conf
   16986                 :            :  *   Shared action configuration.
   16987                 :            :  * @param[in] rss
   16988                 :            :  *   RSS action specification used to create shared action.
   16989                 :            :  * @param[out] error
   16990                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   16991                 :            :  *   error only.
   16992                 :            :  *
   16993                 :            :  * @return
   16994                 :            :  *   A valid shared action ID in case of success, 0 otherwise and
   16995                 :            :  *   rte_errno is set.
   16996                 :            :  */
   16997                 :            : static uint32_t
   16998                 :          0 : __flow_dv_action_rss_create(struct rte_eth_dev *dev,
   16999                 :            :                             const struct rte_flow_indir_action_conf *conf,
   17000                 :            :                             const struct rte_flow_action_rss *rss,
   17001                 :            :                             struct rte_flow_error *error)
   17002                 :            : {
   17003                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17004                 :            :         struct mlx5_shared_action_rss *shared_rss = NULL;
   17005                 :            :         struct rte_flow_action_rss *origin;
   17006                 :            :         const uint8_t *rss_key;
   17007                 :            :         uint32_t idx;
   17008                 :            : 
   17009                 :            :         RTE_SET_USED(conf);
   17010                 :          0 :         shared_rss = mlx5_ipool_zmalloc
   17011                 :          0 :                          (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], &idx);
   17012         [ #  # ]:          0 :         if (!shared_rss) {
   17013                 :          0 :                 rte_flow_error_set(error, ENOMEM,
   17014                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   17015                 :            :                                    "cannot allocate resource memory");
   17016                 :          0 :                 goto error_rss_init;
   17017                 :            :         }
   17018         [ #  # ]:          0 :         if (idx > (1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET)) {
   17019                 :          0 :                 rte_flow_error_set(error, E2BIG,
   17020                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   17021                 :            :                                    "rss action number out of range");
   17022                 :          0 :                 goto error_rss_init;
   17023                 :            :         }
   17024                 :            :         origin = &shared_rss->origin;
   17025                 :          0 :         origin->func = rss->func;
   17026                 :          0 :         origin->level = rss->level;
   17027                 :            :         /* RSS type 0 indicates default RSS type (RTE_ETH_RSS_IP). */
   17028         [ #  # ]:          0 :         origin->types = !rss->types ? RTE_ETH_RSS_IP : rss->types;
   17029                 :            :         /* NULL RSS key indicates default RSS key. */
   17030         [ #  # ]:          0 :         rss_key = !rss->key ? mlx5_rss_hash_default_key : rss->key;
   17031                 :          0 :         memcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
   17032                 :          0 :         origin->key = &shared_rss->key[0];
   17033                 :          0 :         origin->key_len = MLX5_RSS_HASH_KEY_LEN;
   17034                 :          0 :         origin->queue = rss->queue;
   17035                 :          0 :         origin->queue_num = rss->queue_num;
   17036         [ #  # ]:          0 :         if (__flow_dv_action_rss_setup(dev, idx, shared_rss, error))
   17037                 :          0 :                 goto error_rss_init;
   17038                 :            :         /* Update queue with indirect table queue memoyr. */
   17039                 :          0 :         origin->queue = shared_rss->ind_tbl->queues;
   17040                 :            :         rte_spinlock_init(&shared_rss->action_rss_sl);
   17041                 :          0 :         rte_atomic_fetch_add_explicit(&shared_rss->refcnt, 1, rte_memory_order_relaxed);
   17042                 :          0 :         rte_spinlock_lock(&priv->shared_act_sl);
   17043   [ #  #  #  # ]:          0 :         ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   17044                 :            :                      &priv->rss_shared_actions, idx, shared_rss, next);
   17045                 :            :         rte_spinlock_unlock(&priv->shared_act_sl);
   17046                 :          0 :         return idx;
   17047                 :          0 : error_rss_init:
   17048         [ #  # ]:          0 :         if (shared_rss) {
   17049         [ #  # ]:          0 :                 if (shared_rss->ind_tbl)
   17050                 :          0 :                         mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl,
   17051                 :          0 :                                                    !!dev->data->dev_started);
   17052                 :          0 :                 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   17053                 :            :                                 idx);
   17054                 :            :         }
   17055                 :            :         return 0;
   17056                 :            : }
   17057                 :            : 
   17058                 :            : /**
   17059                 :            :  * Destroy the shared RSS action.
   17060                 :            :  * Release related hash RX queue objects.
   17061                 :            :  *
   17062                 :            :  * @param[in] dev
   17063                 :            :  *   Pointer to the Ethernet device structure.
   17064                 :            :  * @param[in] idx
   17065                 :            :  *   The shared RSS action object ID to be removed.
   17066                 :            :  * @param[out] error
   17067                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17068                 :            :  *   error only.
   17069                 :            :  *
   17070                 :            :  * @return
   17071                 :            :  *   0 on success, otherwise negative errno value.
   17072                 :            :  */
   17073                 :            : static int
   17074                 :          0 : __flow_dv_action_rss_release(struct rte_eth_dev *dev, uint32_t idx,
   17075                 :            :                              struct rte_flow_error *error)
   17076                 :            : {
   17077                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17078                 :            :         struct mlx5_shared_action_rss *shared_rss =
   17079                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   17080                 :            :         uint32_t old_refcnt = 1;
   17081                 :            :         int remaining;
   17082                 :            : 
   17083         [ #  # ]:          0 :         if (!shared_rss)
   17084                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   17085                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17086                 :            :                                           "invalid shared action");
   17087         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&shared_rss->refcnt, &old_refcnt,
   17088                 :            :                                          0, rte_memory_order_acquire,
   17089                 :            :                                          rte_memory_order_relaxed))
   17090                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   17091                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17092                 :            :                                           NULL,
   17093                 :            :                                           "shared rss has references");
   17094                 :            :         remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
   17095         [ #  # ]:          0 :         if (remaining)
   17096                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   17097                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17098                 :            :                                           NULL,
   17099                 :            :                                           "shared rss hrxq has references");
   17100                 :          0 :         remaining = mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl,
   17101                 :          0 :                                                !!dev->data->dev_started);
   17102         [ #  # ]:          0 :         if (remaining)
   17103                 :          0 :                 return rte_flow_error_set(error, EBUSY,
   17104                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17105                 :            :                                           NULL,
   17106                 :            :                                           "shared rss indirection table has"
   17107                 :            :                                           " references");
   17108                 :          0 :         rte_spinlock_lock(&priv->shared_act_sl);
   17109   [ #  #  #  #  :          0 :         ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
          #  #  #  #  #  
                      # ]
   17110                 :            :                      &priv->rss_shared_actions, idx, shared_rss, next);
   17111                 :            :         rte_spinlock_unlock(&priv->shared_act_sl);
   17112                 :          0 :         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
   17113                 :            :                         idx);
   17114                 :          0 :         return 0;
   17115                 :            : }
   17116                 :            : 
   17117                 :            : /**
   17118                 :            :  * Create indirect action, lock free,
   17119                 :            :  * (mutex should be acquired by caller).
   17120                 :            :  * Dispatcher for action type specific call.
   17121                 :            :  *
   17122                 :            :  * @param[in] dev
   17123                 :            :  *   Pointer to the Ethernet device structure.
   17124                 :            :  * @param[in] conf
   17125                 :            :  *   Shared action configuration.
   17126                 :            :  * @param[in] action
   17127                 :            :  *   Action specification used to create indirect action.
   17128                 :            :  * @param[out] error
   17129                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17130                 :            :  *   error only.
   17131                 :            :  *
   17132                 :            :  * @return
   17133                 :            :  *   A valid shared action handle in case of success, NULL otherwise and
   17134                 :            :  *   rte_errno is set.
   17135                 :            :  */
   17136                 :            : struct rte_flow_action_handle *
   17137                 :          0 : mlx5_flow_dv_action_create(struct rte_eth_dev *dev,
   17138                 :            :                            const struct rte_flow_indir_action_conf *conf,
   17139                 :            :                            const struct rte_flow_action *action,
   17140                 :            :                            struct rte_flow_error *err)
   17141                 :            : {
   17142                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17143                 :            :         uint32_t age_idx = 0;
   17144                 :            :         uint32_t idx = 0;
   17145                 :            :         uint32_t ret = 0;
   17146                 :            : 
   17147   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   17148                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   17149                 :          0 :                 ret = __flow_dv_action_rss_create(dev, conf, action->conf, err);
   17150                 :            :                 idx = (MLX5_INDIRECT_ACTION_TYPE_RSS <<
   17151                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | ret;
   17152                 :          0 :                 break;
   17153                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   17154                 :          0 :                 age_idx = flow_dv_aso_age_alloc(dev, err);
   17155         [ #  # ]:          0 :                 if (!age_idx) {
   17156                 :          0 :                         ret = -rte_errno;
   17157                 :          0 :                         break;
   17158                 :            :                 }
   17159                 :          0 :                 idx = (MLX5_INDIRECT_ACTION_TYPE_AGE <<
   17160                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | age_idx;
   17161                 :          0 :                 flow_dv_aso_age_params_init(dev, age_idx,
   17162                 :            :                                         ((const struct rte_flow_action_age *)
   17163                 :          0 :                                                 action->conf)->context ?
   17164                 :            :                                         ((const struct rte_flow_action_age *)
   17165                 :            :                                                 action->conf)->context :
   17166                 :          0 :                                         (void *)(uintptr_t)idx,
   17167                 :            :                                         ((const struct rte_flow_action_age *)
   17168         [ #  # ]:          0 :                                                 action->conf)->timeout);
   17169                 :            :                 ret = age_idx;
   17170                 :          0 :                 break;
   17171                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   17172                 :          0 :                 ret = flow_dv_translate_create_counter(dev, NULL, NULL, NULL);
   17173                 :          0 :                 idx = (MLX5_INDIRECT_ACTION_TYPE_COUNT <<
   17174                 :            :                        MLX5_INDIRECT_ACTION_TYPE_OFFSET) | ret;
   17175                 :          0 :                 break;
   17176                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   17177                 :          0 :                 ret = flow_dv_translate_create_conntrack(dev, action->conf,
   17178                 :            :                                                          err);
   17179         [ #  # ]:          0 :                 if (!ret)
   17180                 :            :                         break;
   17181                 :          0 :                 idx = MLX5_INDIRECT_ACT_CT_GEN_IDX(PORT_ID(priv), ret);
   17182                 :          0 :                 break;
   17183                 :          0 :         default:
   17184                 :          0 :                 rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
   17185                 :            :                                    NULL, "action type not supported");
   17186                 :            :                 break;
   17187                 :            :         }
   17188         [ #  # ]:          0 :         return ret ? (struct rte_flow_action_handle *)(uintptr_t)idx : NULL;
   17189                 :            : }
   17190                 :            : 
   17191                 :            : /**
   17192                 :            :  * Destroy the indirect action.
   17193                 :            :  * Release action related resources on the NIC and the memory.
   17194                 :            :  * Lock free, (mutex should be acquired by caller).
   17195                 :            :  * Dispatcher for action type specific call.
   17196                 :            :  *
   17197                 :            :  * @param[in] dev
   17198                 :            :  *   Pointer to the Ethernet device structure.
   17199                 :            :  * @param[in] handle
   17200                 :            :  *   The indirect action object handle to be removed.
   17201                 :            :  * @param[out] error
   17202                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17203                 :            :  *   error only.
   17204                 :            :  *
   17205                 :            :  * @return
   17206                 :            :  *   0 on success, otherwise negative errno value.
   17207                 :            :  */
   17208                 :            : int
   17209                 :          0 : mlx5_flow_dv_action_destroy(struct rte_eth_dev *dev,
   17210                 :            :                             struct rte_flow_action_handle *handle,
   17211                 :            :                             struct rte_flow_error *error)
   17212                 :            : {
   17213                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   17214                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   17215                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   17216                 :            :         struct mlx5_flow_counter *cnt;
   17217                 :            :         uint32_t no_flow_refcnt = 1;
   17218                 :            :         int ret;
   17219                 :            : 
   17220   [ #  #  #  #  :          0 :         switch (type) {
                      # ]
   17221                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   17222                 :          0 :                 return __flow_dv_action_rss_release(dev, idx, error);
   17223                 :            :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   17224                 :            :                 cnt = flow_dv_counter_get_by_idx(dev, idx, NULL);
   17225         [ #  # ]:          0 :                 if (!rte_atomic_compare_exchange_strong_explicit(&cnt->shared_info.refcnt,
   17226                 :            :                                                  &no_flow_refcnt, 1,
   17227                 :            :                                                  rte_memory_order_acquire,
   17228                 :            :                                                  rte_memory_order_relaxed))
   17229                 :          0 :                         return rte_flow_error_set(error, EBUSY,
   17230                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   17231                 :            :                                                   NULL,
   17232                 :            :                                                   "Indirect count action has references");
   17233                 :          0 :                 flow_dv_counter_free(dev, idx);
   17234                 :          0 :                 return 0;
   17235                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   17236                 :          0 :                 ret = flow_dv_aso_age_release(dev, idx);
   17237         [ #  # ]:          0 :                 if (ret)
   17238                 :            :                         /*
   17239                 :            :                          * In this case, the last flow has a reference will
   17240                 :            :                          * actually release the age action.
   17241                 :            :                          */
   17242                 :          0 :                         DRV_LOG(DEBUG, "Indirect age action %" PRIu32 " was"
   17243                 :            :                                 " released with references %d.", idx, ret);
   17244                 :            :                 return 0;
   17245                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   17246                 :          0 :                 ret = flow_dv_aso_ct_release(dev, idx, error);
   17247         [ #  # ]:          0 :                 if (ret < 0)
   17248                 :            :                         return ret;
   17249         [ #  # ]:          0 :                 if (ret > 0)
   17250                 :          0 :                         DRV_LOG(DEBUG, "Connection tracking object %u still "
   17251                 :            :                                 "has references %d.", idx, ret);
   17252                 :            :                 return 0;
   17253                 :          0 :         default:
   17254                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17255                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17256                 :            :                                           NULL,
   17257                 :            :                                           "action type not supported");
   17258                 :            :         }
   17259                 :            : }
   17260                 :            : 
   17261                 :            : /**
   17262                 :            :  * Updates in place shared RSS action configuration.
   17263                 :            :  *
   17264                 :            :  * @param[in] dev
   17265                 :            :  *   Pointer to the Ethernet device structure.
   17266                 :            :  * @param[in] idx
   17267                 :            :  *   The shared RSS action object ID to be updated.
   17268                 :            :  * @param[in] action_conf
   17269                 :            :  *   RSS action specification used to modify *shared_rss*.
   17270                 :            :  * @param[out] error
   17271                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17272                 :            :  *   error only.
   17273                 :            :  *
   17274                 :            :  * @return
   17275                 :            :  *   0 on success, otherwise negative errno value.
   17276                 :            :  * @note: currently only support update of RSS queues.
   17277                 :            :  */
   17278                 :            : static int
   17279                 :          0 : __flow_dv_action_rss_update(struct rte_eth_dev *dev, uint32_t idx,
   17280                 :            :                             const struct rte_flow_action_rss *action_conf,
   17281                 :            :                             struct rte_flow_error *error)
   17282                 :            : {
   17283                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17284                 :            :         struct mlx5_shared_action_rss *shared_rss =
   17285                 :          0 :             mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
   17286                 :            :         int ret = 0;
   17287                 :            :         void *queue = NULL;
   17288                 :            :         void *queue_i = NULL;
   17289                 :          0 :         uint32_t queue_size = action_conf->queue_num * sizeof(uint16_t);
   17290                 :          0 :         bool dev_started = !!dev->data->dev_started;
   17291                 :            : 
   17292         [ #  # ]:          0 :         if (!shared_rss)
   17293                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   17294                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17295                 :            :                                           "invalid shared action to update");
   17296         [ #  # ]:          0 :         if (priv->obj_ops.ind_table_modify == NULL)
   17297                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   17298                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17299                 :            :                                           "cannot modify indirection table");
   17300                 :          0 :         queue = mlx5_malloc(MLX5_MEM_ZERO,
   17301                 :          0 :                             RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
   17302                 :            :                             0, SOCKET_ID_ANY);
   17303         [ #  # ]:          0 :         if (!queue)
   17304                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   17305                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17306                 :            :                                           NULL,
   17307                 :            :                                           "cannot allocate resource memory");
   17308                 :          0 :         memcpy(queue, action_conf->queue, queue_size);
   17309                 :            :         MLX5_ASSERT(shared_rss->ind_tbl);
   17310                 :          0 :         rte_spinlock_lock(&shared_rss->action_rss_sl);
   17311                 :          0 :         queue_i = shared_rss->ind_tbl->queues;
   17312                 :          0 :         ret = mlx5_ind_table_obj_modify(dev, shared_rss->ind_tbl,
   17313                 :          0 :                                         queue, action_conf->queue_num,
   17314                 :            :                                         true /* standalone */,
   17315                 :            :                                         dev_started /* ref_new_qs */,
   17316                 :            :                                         dev_started /* deref_old_qs */);
   17317         [ #  # ]:          0 :         if (ret) {
   17318                 :          0 :                 ret = rte_flow_error_set(error, rte_errno,
   17319                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   17320                 :            :                                           "cannot update indirection table");
   17321                 :            :         } else {
   17322                 :            :                 /* Restore the queue to indirect table internal queue. */
   17323                 :            :                 memcpy(queue_i, queue, queue_size);
   17324                 :          0 :                 shared_rss->ind_tbl->queues = queue_i;
   17325                 :          0 :                 shared_rss->origin.queue_num = action_conf->queue_num;
   17326                 :            :         }
   17327                 :          0 :         mlx5_free(queue);
   17328                 :            :         rte_spinlock_unlock(&shared_rss->action_rss_sl);
   17329                 :          0 :         return ret;
   17330                 :            : }
   17331                 :            : 
   17332                 :            : /*
   17333                 :            :  * Updates in place conntrack context or direction.
   17334                 :            :  * Context update should be synchronized.
   17335                 :            :  *
   17336                 :            :  * @param[in] dev
   17337                 :            :  *   Pointer to the Ethernet device structure.
   17338                 :            :  * @param[in] idx
   17339                 :            :  *   The conntrack object ID to be updated.
   17340                 :            :  * @param[in] update
   17341                 :            :  *   Pointer to the structure of information to update.
   17342                 :            :  * @param[out] error
   17343                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17344                 :            :  *   error only.
   17345                 :            :  *
   17346                 :            :  * @return
   17347                 :            :  *   0 on success, otherwise negative errno value.
   17348                 :            :  */
   17349                 :            : static int
   17350                 :          0 : __flow_dv_action_ct_update(struct rte_eth_dev *dev, uint32_t idx,
   17351                 :            :                            const struct rte_flow_modify_conntrack *update,
   17352                 :            :                            struct rte_flow_error *error)
   17353                 :            : {
   17354                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17355                 :            :         struct mlx5_aso_ct_action *ct;
   17356                 :            :         const struct rte_flow_action_conntrack *new_prf;
   17357                 :            :         int ret = 0;
   17358                 :          0 :         uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(idx);
   17359                 :            :         uint32_t dev_idx;
   17360                 :            : 
   17361         [ #  # ]:          0 :         if (PORT_ID(priv) != owner)
   17362                 :          0 :                 return rte_flow_error_set(error, EACCES,
   17363                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17364                 :            :                                           NULL,
   17365                 :            :                                           "CT object owned by another port");
   17366                 :          0 :         dev_idx = MLX5_INDIRECT_ACT_CT_GET_IDX(idx);
   17367                 :          0 :         ct = flow_aso_ct_get_by_dev_idx(dev, dev_idx);
   17368         [ #  # ]:          0 :         if (!ct->refcnt)
   17369                 :          0 :                 return rte_flow_error_set(error, ENOMEM,
   17370                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17371                 :            :                                           NULL,
   17372                 :            :                                           "CT object is inactive");
   17373                 :          0 :         new_prf = &update->new_ct;
   17374         [ #  # ]:          0 :         if (update->direction)
   17375                 :          0 :                 ct->is_original = !!new_prf->is_original_dir;
   17376         [ #  # ]:          0 :         if (update->state) {
   17377                 :            :                 /* Only validate the profile when it needs to be updated. */
   17378                 :          0 :                 ret = mlx5_validate_action_ct(dev, new_prf, error);
   17379         [ #  # ]:          0 :                 if (ret)
   17380                 :            :                         return ret;
   17381                 :          0 :                 ret = mlx5_aso_ct_update_by_wqe(priv->sh, MLX5_HW_INV_QUEUE,
   17382                 :            :                                                 ct, new_prf, NULL, true);
   17383         [ #  # ]:          0 :                 if (ret)
   17384                 :          0 :                         return rte_flow_error_set(error, EIO,
   17385                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17386                 :            :                                         NULL,
   17387                 :            :                                         "Failed to send CT context update WQE");
   17388                 :            :                 /* Block until ready or a failure, default is asynchronous. */
   17389                 :          0 :                 ret = mlx5_aso_ct_available(priv->sh, MLX5_HW_INV_QUEUE, ct);
   17390         [ #  # ]:          0 :                 if (ret)
   17391                 :          0 :                         rte_flow_error_set(error, rte_errno,
   17392                 :            :                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   17393                 :            :                                            NULL,
   17394                 :            :                                            "Timeout to get the CT update");
   17395                 :            :         }
   17396                 :            :         return ret;
   17397                 :            : }
   17398                 :            : 
   17399                 :            : /**
   17400                 :            :  * Updates in place shared action configuration, lock free,
   17401                 :            :  * (mutex should be acquired by caller).
   17402                 :            :  *
   17403                 :            :  * @param[in] dev
   17404                 :            :  *   Pointer to the Ethernet device structure.
   17405                 :            :  * @param[in] handle
   17406                 :            :  *   The indirect action object handle to be updated.
   17407                 :            :  * @param[in] update
   17408                 :            :  *   Action specification used to modify the action pointed by *handle*.
   17409                 :            :  *   *update* could be of same type with the action pointed by the *handle*
   17410                 :            :  *   handle argument, or some other structures like a wrapper, depending on
   17411                 :            :  *   the indirect action type.
   17412                 :            :  * @param[out] error
   17413                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17414                 :            :  *   error only.
   17415                 :            :  *
   17416                 :            :  * @return
   17417                 :            :  *   0 on success, otherwise negative errno value.
   17418                 :            :  */
   17419                 :            : int
   17420                 :          0 : mlx5_flow_dv_action_update(struct rte_eth_dev *dev,
   17421                 :            :                            struct rte_flow_action_handle *handle,
   17422                 :            :                            const void *update,
   17423                 :            :                            struct rte_flow_error *err)
   17424                 :            : {
   17425                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   17426                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   17427                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   17428                 :            :         const void *action_conf;
   17429                 :            : 
   17430      [ #  #  # ]:          0 :         switch (type) {
   17431                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_RSS:
   17432                 :          0 :                 action_conf = ((const struct rte_flow_action *)update)->conf;
   17433                 :          0 :                 return __flow_dv_action_rss_update(dev, idx, action_conf, err);
   17434                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   17435                 :          0 :                 return __flow_dv_action_ct_update(dev, idx, update, err);
   17436                 :          0 :         default:
   17437                 :          0 :                 return rte_flow_error_set(err, ENOTSUP,
   17438                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   17439                 :            :                                           NULL,
   17440                 :            :                                           "action type update not supported");
   17441                 :            :         }
   17442                 :            : }
   17443                 :            : 
   17444                 :            : /**
   17445                 :            :  * Destroy the meter sub policy table rules.
   17446                 :            :  * Lock free, (mutex should be acquired by caller).
   17447                 :            :  *
   17448                 :            :  * @param[in] dev
   17449                 :            :  *   Pointer to Ethernet device.
   17450                 :            :  * @param[in] sub_policy
   17451                 :            :  *   Pointer to meter sub policy table.
   17452                 :            :  */
   17453                 :            : static void
   17454                 :          0 : __flow_dv_destroy_sub_policy_rules(struct rte_eth_dev *dev,
   17455                 :            :                              struct mlx5_flow_meter_sub_policy *sub_policy)
   17456                 :            : {
   17457                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17458                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   17459                 :          0 :         struct mlx5_flow_meter_policy *policy = sub_policy->main_policy;
   17460                 :            :         struct mlx5_flow_meter_info *next_fm;
   17461                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   17462                 :            :         void *tmp;
   17463                 :            :         uint32_t i;
   17464                 :            : 
   17465         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   17466                 :            :                 next_fm = NULL;
   17467         [ #  # ]:          0 :                 if (i <= RTE_COLOR_YELLOW && policy &&
   17468         [ #  # ]:          0 :                     policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR)
   17469                 :          0 :                         next_fm = mlx5_flow_meter_find(priv,
   17470                 :            :                                         policy->act_cnt[i].next_mtr_id, NULL);
   17471         [ #  # ]:          0 :                 RTE_TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
   17472                 :            :                                    next_port, tmp) {
   17473                 :          0 :                         claim_zero(mlx5_flow_os_destroy_flow(color_rule->rule));
   17474                 :          0 :                         tbl = container_of(color_rule->matcher->tbl,
   17475                 :            :                                            typeof(*tbl), tbl);
   17476                 :          0 :                         mlx5_list_unregister(tbl->matchers,
   17477                 :            :                                              &color_rule->matcher->entry);
   17478         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[i],
   17479                 :            :                                      color_rule, next_port);
   17480                 :          0 :                         mlx5_free(color_rule);
   17481         [ #  # ]:          0 :                         if (next_fm)
   17482                 :          0 :                                 mlx5_flow_meter_detach(priv, next_fm);
   17483                 :            :                 }
   17484                 :            :         }
   17485         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   17486         [ #  # ]:          0 :                 if (sub_policy->rix_hrxq[i]) {
   17487   [ #  #  #  # ]:          0 :                         if (policy && !policy->is_hierarchy)
   17488                 :          0 :                                 mlx5_hrxq_release(dev, sub_policy->rix_hrxq[i]);
   17489                 :          0 :                         sub_policy->rix_hrxq[i] = 0;
   17490                 :            :                 }
   17491         [ #  # ]:          0 :                 if (sub_policy->jump_tbl[i]) {
   17492                 :          0 :                         mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), sub_policy->jump_tbl[i]);
   17493                 :          0 :                         sub_policy->jump_tbl[i] = NULL;
   17494                 :            :                 }
   17495                 :            :         }
   17496         [ #  # ]:          0 :         if (sub_policy->tbl_rsc) {
   17497                 :          0 :                 mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), sub_policy->tbl_rsc);
   17498                 :          0 :                 sub_policy->tbl_rsc = NULL;
   17499                 :            :         }
   17500                 :          0 : }
   17501                 :            : 
   17502                 :            : /**
   17503                 :            :  * Destroy policy rules, lock free,
   17504                 :            :  * (mutex should be acquired by caller).
   17505                 :            :  * Dispatcher for action type specific call.
   17506                 :            :  *
   17507                 :            :  * @param[in] dev
   17508                 :            :  *   Pointer to the Ethernet device structure.
   17509                 :            :  * @param[in] mtr_policy
   17510                 :            :  *   Meter policy struct.
   17511                 :            :  */
   17512                 :            : static void
   17513                 :          0 : flow_dv_destroy_policy_rules(struct rte_eth_dev *dev,
   17514                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
   17515                 :            : {
   17516                 :            :         uint32_t i, j;
   17517                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   17518                 :            :         uint16_t sub_policy_num;
   17519                 :            : 
   17520         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   17521                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   17522                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   17523                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   17524         [ #  # ]:          0 :                 for (j = 0; j < sub_policy_num; j++) {
   17525                 :          0 :                         sub_policy = mtr_policy->sub_policys[i][j];
   17526         [ #  # ]:          0 :                         if (sub_policy)
   17527                 :          0 :                                 __flow_dv_destroy_sub_policy_rules(dev,
   17528                 :            :                                                                    sub_policy);
   17529                 :            :                 }
   17530                 :            :         }
   17531                 :          0 : }
   17532                 :            : 
   17533                 :            : /**
   17534                 :            :  * Destroy policy action, lock free,
   17535                 :            :  * (mutex should be acquired by caller).
   17536                 :            :  * Dispatcher for action type specific call.
   17537                 :            :  *
   17538                 :            :  * @param[in] dev
   17539                 :            :  *   Pointer to the Ethernet device structure.
   17540                 :            :  * @param[in] mtr_policy
   17541                 :            :  *   Meter policy struct.
   17542                 :            :  */
   17543                 :            : static void
   17544                 :          0 : flow_dv_destroy_mtr_policy_acts(struct rte_eth_dev *dev,
   17545                 :            :                       struct mlx5_flow_meter_policy *mtr_policy)
   17546                 :            : {
   17547                 :            :         struct rte_flow_action *rss_action;
   17548                 :            :         struct mlx5_flow_handle dev_handle;
   17549                 :            :         uint32_t i, j;
   17550                 :            : 
   17551         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   17552         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].rix_mark) {
   17553                 :          0 :                         flow_dv_tag_release(dev,
   17554                 :            :                                 mtr_policy->act_cnt[i].rix_mark);
   17555                 :          0 :                         mtr_policy->act_cnt[i].rix_mark = 0;
   17556                 :            :                 }
   17557         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].modify_hdr) {
   17558                 :            :                         dev_handle.dvh.modify_hdr =
   17559                 :            :                                 mtr_policy->act_cnt[i].modify_hdr;
   17560                 :            :                         flow_dv_modify_hdr_resource_release(dev, &dev_handle);
   17561                 :            :                 }
   17562   [ #  #  #  # ]:          0 :                 switch (mtr_policy->act_cnt[i].fate_action) {
   17563                 :          0 :                 case MLX5_FLOW_FATE_SHARED_RSS:
   17564                 :          0 :                         rss_action = mtr_policy->act_cnt[i].rss;
   17565                 :          0 :                         mlx5_free(rss_action);
   17566                 :          0 :                         break;
   17567                 :          0 :                 case MLX5_FLOW_FATE_PORT_ID:
   17568         [ #  # ]:          0 :                         if (mtr_policy->act_cnt[i].rix_port_id_action) {
   17569                 :          0 :                                 flow_dv_port_id_action_resource_release(dev,
   17570                 :            :                                 mtr_policy->act_cnt[i].rix_port_id_action);
   17571                 :          0 :                                 mtr_policy->act_cnt[i].rix_port_id_action = 0;
   17572                 :            :                         }
   17573                 :            :                         break;
   17574                 :            :                 case MLX5_FLOW_FATE_DROP:
   17575                 :            :                 case MLX5_FLOW_FATE_JUMP:
   17576         [ #  # ]:          0 :                         for (j = 0; j < MLX5_MTR_DOMAIN_MAX; j++)
   17577                 :          0 :                                 mtr_policy->act_cnt[i].dr_jump_action[j] =
   17578                 :            :                                                 NULL;
   17579                 :            :                         break;
   17580                 :            :                 default:
   17581                 :            :                         /*Queue action do nothing*/
   17582                 :            :                         break;
   17583                 :            :                 }
   17584                 :            :         }
   17585         [ #  # ]:          0 :         for (j = 0; j < MLX5_MTR_DOMAIN_MAX; j++)
   17586                 :          0 :                 mtr_policy->dr_drop_action[j] = NULL;
   17587                 :          0 : }
   17588                 :            : 
   17589                 :            : /**
   17590                 :            :  * Create yellow action for color aware meter.
   17591                 :            :  *
   17592                 :            :  * @param[in] dev
   17593                 :            :  *   Pointer to the Ethernet device structure.
   17594                 :            :  * @param[in] fm
   17595                 :            :  *   Meter information table.
   17596                 :            :  * @param[out] error
   17597                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17598                 :            :  *   error only.
   17599                 :            :  *
   17600                 :            :  * @return
   17601                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   17602                 :            :  */
   17603                 :            : static int
   17604                 :          0 : __flow_dv_create_mtr_yellow_action(struct rte_eth_dev *dev,
   17605                 :            :                                    struct mlx5_flow_meter_info *fm,
   17606                 :            :                                    struct rte_mtr_error *error)
   17607                 :            : {
   17608                 :            : #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
   17609                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17610                 :            :         struct rte_flow_error flow_err;
   17611                 :            :         struct mlx5_aso_mtr *aso_mtr;
   17612                 :            :         struct mlx5_aso_mtr_pool *pool;
   17613                 :            :         uint8_t reg_id;
   17614                 :            : 
   17615                 :          0 :         aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
   17616                 :          0 :         pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool, mtrs[aso_mtr->offset]);
   17617                 :          0 :         reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &flow_err);
   17618                 :          0 :         fm->meter_action_y =
   17619                 :          0 :                 mlx5_glue->dv_create_flow_action_aso(priv->sh->rx_domain,
   17620                 :          0 :                                                      pool->devx_obj->obj,
   17621                 :            :                                                      aso_mtr->offset,
   17622                 :            :                                                      (1 << MLX5_FLOW_COLOR_YELLOW),
   17623                 :          0 :                                                      reg_id - REG_C_0);
   17624                 :            : #else
   17625                 :            :         RTE_SET_USED(dev);
   17626                 :            : #endif
   17627         [ #  # ]:          0 :         if (!fm->meter_action_y) {
   17628                 :          0 :                 return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17629                 :            :                                           "Fail to create yellow meter action.");
   17630                 :            :         }
   17631                 :            :         return 0;
   17632                 :            : }
   17633                 :            : 
   17634                 :            : /**
   17635                 :            :  * Create policy action per domain, lock free,
   17636                 :            :  * (mutex should be acquired by caller).
   17637                 :            :  * Dispatcher for action type specific call.
   17638                 :            :  *
   17639                 :            :  * @param[in] dev
   17640                 :            :  *   Pointer to the Ethernet device structure.
   17641                 :            :  * @param[in] mtr_policy
   17642                 :            :  *   Meter policy struct.
   17643                 :            :  * @param[in] action
   17644                 :            :  *   Action specification used to create meter actions.
   17645                 :            :  * @param[in] attr
   17646                 :            :  *   Pointer to the flow attributes.
   17647                 :            :  * @param[out] error
   17648                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   17649                 :            :  *   error only.
   17650                 :            :  *
   17651                 :            :  * @return
   17652                 :            :  *   0 on success, otherwise negative errno value.
   17653                 :            :  */
   17654                 :            : static int
   17655                 :          0 : __flow_dv_create_domain_policy_acts(struct rte_eth_dev *dev,
   17656                 :            :                         struct mlx5_flow_meter_policy *mtr_policy,
   17657                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
   17658                 :            :                         struct rte_flow_attr *attr,
   17659                 :            :                         enum mlx5_meter_domain domain,
   17660                 :            :                         struct rte_mtr_error *error)
   17661                 :            : {
   17662                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   17663                 :            :         struct rte_flow_error flow_err;
   17664                 :            :         const struct rte_flow_action *act;
   17665                 :            :         uint64_t action_flags;
   17666                 :            :         struct mlx5_flow_handle dh;
   17667                 :            :         struct mlx5_flow dev_flow;
   17668                 :            :         struct mlx5_flow_dv_port_id_action_resource port_id_action;
   17669                 :            :         int i, ret;
   17670                 :            :         uint8_t egress, transfer;
   17671                 :            :         struct mlx5_meter_policy_action_container *act_cnt = NULL;
   17672                 :            :         union {
   17673                 :            :                 struct mlx5_flow_dv_modify_hdr_resource res;
   17674                 :            :                 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
   17675                 :            :                             sizeof(struct mlx5_modification_cmd) *
   17676                 :            :                             (MLX5_MAX_MODIFY_NUM + 1)];
   17677                 :            :         } mhdr_dummy;
   17678                 :            :         struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
   17679                 :            : 
   17680                 :          0 :         egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   17681         [ #  # ]:          0 :         transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   17682                 :            :         memset(&dh, 0, sizeof(struct mlx5_flow_handle));
   17683                 :            :         memset(&dev_flow, 0, sizeof(struct mlx5_flow));
   17684                 :            :         memset(&port_id_action, 0,
   17685                 :            :                sizeof(struct mlx5_flow_dv_port_id_action_resource));
   17686                 :            :         memset(mhdr_res, 0, sizeof(*mhdr_res));
   17687         [ #  # ]:          0 :         mhdr_res->ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB :
   17688                 :            :                                        (egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
   17689                 :            :                                         MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
   17690                 :          0 :         dev_flow.handle = &dh;
   17691                 :          0 :         dev_flow.dv.port_id_action = &port_id_action;
   17692                 :          0 :         dev_flow.external = true;
   17693         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   17694         [ #  # ]:          0 :                 if (i < MLX5_MTR_RTE_COLORS)
   17695                 :          0 :                         act_cnt = &mtr_policy->act_cnt[i];
   17696                 :            :                 /* Skip the color policy actions creation. */
   17697   [ #  #  #  #  :          0 :                 if ((i == RTE_COLOR_YELLOW && mtr_policy->skip_y) ||
                   #  # ]
   17698         [ #  # ]:          0 :                     (i == RTE_COLOR_GREEN && mtr_policy->skip_g))
   17699                 :          0 :                         continue;
   17700                 :            :                 action_flags = 0;
   17701                 :          0 :                 for (act = actions[i];
   17702   [ #  #  #  # ]:          0 :                      act && act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
   17703   [ #  #  #  #  :          0 :                         switch (act->type) {
          #  #  #  #  #  
                      # ]
   17704                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MARK:
   17705                 :            :                         {
   17706                 :            :                                 uint32_t tag_be = mlx5_flow_mark_set
   17707                 :            :                                         (((const struct rte_flow_action_mark *)
   17708         [ #  # ]:          0 :                                         (act->conf))->id);
   17709                 :            : 
   17710         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17711                 :          0 :                                         return -rte_mtr_error_set(error,
   17712                 :            :                                           ENOTSUP,
   17713                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17714                 :            :                                           NULL,
   17715                 :            :                                           "cannot create policy "
   17716                 :            :                                           "mark action for this color");
   17717         [ #  # ]:          0 :                                 if (flow_dv_tag_resource_register(dev, tag_be,
   17718                 :            :                                                   &dev_flow, &flow_err))
   17719                 :          0 :                                         return -rte_mtr_error_set(error,
   17720                 :            :                                         ENOTSUP,
   17721                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17722                 :            :                                         NULL,
   17723                 :            :                                         "cannot setup policy mark action");
   17724                 :            :                                 MLX5_ASSERT(dev_flow.dv.tag_resource);
   17725                 :          0 :                                 act_cnt->rix_mark =
   17726                 :          0 :                                         dev_flow.handle->dvh.rix_tag;
   17727                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MARK;
   17728                 :          0 :                                 mtr_policy->mark = 1;
   17729                 :          0 :                                 break;
   17730                 :            :                         }
   17731                 :          0 :                         case RTE_FLOW_ACTION_TYPE_SET_TAG:
   17732         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17733                 :          0 :                                         return -rte_mtr_error_set(error,
   17734                 :            :                                           ENOTSUP,
   17735                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17736                 :            :                                           NULL,
   17737                 :            :                                           "cannot create policy "
   17738                 :            :                                           "set tag action for this color");
   17739         [ #  # ]:          0 :                                 if (flow_dv_convert_action_set_tag
   17740                 :            :                                 (dev, mhdr_res,
   17741                 :            :                                 (const struct rte_flow_action_set_tag *)
   17742                 :          0 :                                 act->conf,  &flow_err))
   17743                 :          0 :                                         return -rte_mtr_error_set(error,
   17744                 :            :                                         ENOTSUP,
   17745                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17746                 :            :                                         NULL, "cannot convert policy "
   17747                 :            :                                         "set tag action");
   17748         [ #  # ]:          0 :                                 if (!mhdr_res->actions_num)
   17749                 :          0 :                                         return -rte_mtr_error_set(error,
   17750                 :            :                                         ENOTSUP,
   17751                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17752                 :            :                                         NULL, "cannot find policy "
   17753                 :            :                                         "set tag action");
   17754                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_SET_TAG;
   17755                 :          0 :                                 break;
   17756                 :          0 :                         case RTE_FLOW_ACTION_TYPE_DROP:
   17757                 :            :                         {
   17758                 :          0 :                                 struct mlx5_flow_mtr_mng *mtrmng =
   17759                 :          0 :                                                 priv->sh->mtrmng;
   17760                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl_data;
   17761                 :            : 
   17762                 :            :                                 /*
   17763                 :            :                                  * Create the drop table with
   17764                 :            :                                  * METER DROP level.
   17765                 :            :                                  */
   17766         [ #  # ]:          0 :                                 if (!mtrmng->drop_tbl[domain]) {
   17767                 :          0 :                                         mtrmng->drop_tbl[domain] =
   17768                 :          0 :                                         mlx5_flow_dv_tbl_resource_get(dev,
   17769                 :            :                                                                       MLX5_FLOW_TABLE_LEVEL_METER,
   17770                 :            :                                                                       egress, transfer, false,
   17771                 :            :                                                                       NULL, 0,
   17772                 :            :                                                                       0, MLX5_MTR_TABLE_ID_DROP,
   17773                 :            :                                                                       &flow_err);
   17774         [ #  # ]:          0 :                                         if (!mtrmng->drop_tbl[domain])
   17775                 :          0 :                                                 return -rte_mtr_error_set
   17776                 :            :                                         (error, ENOTSUP,
   17777                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17778                 :            :                                         NULL,
   17779                 :            :                                         "Failed to create meter drop table");
   17780                 :            :                                 }
   17781                 :          0 :                                 tbl_data = container_of
   17782                 :            :                                 (mtrmng->drop_tbl[domain],
   17783                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17784         [ #  # ]:          0 :                                 if (i < MLX5_MTR_RTE_COLORS) {
   17785                 :          0 :                                         act_cnt->dr_jump_action[domain] =
   17786                 :          0 :                                                 tbl_data->jump.action;
   17787                 :          0 :                                         act_cnt->fate_action =
   17788                 :            :                                                 MLX5_FLOW_FATE_DROP;
   17789                 :            :                                 }
   17790         [ #  # ]:          0 :                                 if (i == RTE_COLOR_RED)
   17791                 :          0 :                                         mtr_policy->dr_drop_action[domain] =
   17792                 :          0 :                                                 tbl_data->jump.action;
   17793                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_DROP;
   17794                 :          0 :                                 break;
   17795                 :            :                         }
   17796                 :          0 :                         case RTE_FLOW_ACTION_TYPE_QUEUE:
   17797                 :            :                         {
   17798         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17799                 :          0 :                                         return -rte_mtr_error_set(error,
   17800                 :            :                                         ENOTSUP,
   17801                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17802                 :            :                                         NULL, "cannot create policy "
   17803                 :            :                                         "fate queue for this color");
   17804                 :          0 :                                 act_cnt->queue =
   17805                 :            :                                 ((const struct rte_flow_action_queue *)
   17806                 :          0 :                                         (act->conf))->index;
   17807                 :          0 :                                 act_cnt->fate_action =
   17808                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   17809                 :          0 :                                 dev_flow.handle->fate_action =
   17810                 :            :                                         MLX5_FLOW_FATE_QUEUE;
   17811                 :          0 :                                 mtr_policy->is_queue = 1;
   17812                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_QUEUE;
   17813                 :          0 :                                 break;
   17814                 :            :                         }
   17815                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RSS:
   17816                 :            :                         {
   17817                 :            :                                 int rss_size;
   17818                 :            : 
   17819         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17820                 :          0 :                                         return -rte_mtr_error_set(error,
   17821                 :            :                                           ENOTSUP,
   17822                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17823                 :            :                                           NULL,
   17824                 :            :                                           "cannot create policy "
   17825                 :            :                                           "rss action for this color");
   17826                 :            :                                 /*
   17827                 :            :                                  * Save RSS conf into policy struct
   17828                 :            :                                  * for translate stage.
   17829                 :            :                                  */
   17830                 :          0 :                                 rss_size = (int)rte_flow_conv
   17831                 :            :                                         (RTE_FLOW_CONV_OP_ACTION,
   17832                 :            :                                         NULL, 0, act, &flow_err);
   17833         [ #  # ]:          0 :                                 if (rss_size <= 0)
   17834                 :          0 :                                         return -rte_mtr_error_set(error,
   17835                 :            :                                           ENOTSUP,
   17836                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17837                 :            :                                           NULL, "Get the wrong "
   17838                 :            :                                           "rss action struct size");
   17839                 :          0 :                                 act_cnt->rss = mlx5_malloc(MLX5_MEM_ZERO,
   17840                 :            :                                                 rss_size, 0, SOCKET_ID_ANY);
   17841         [ #  # ]:          0 :                                 if (!act_cnt->rss)
   17842                 :          0 :                                         return -rte_mtr_error_set(error,
   17843                 :            :                                           ENOTSUP,
   17844                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17845                 :            :                                           NULL,
   17846                 :            :                                           "Fail to malloc rss action memory");
   17847                 :          0 :                                 ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTION,
   17848                 :            :                                         act_cnt->rss, rss_size,
   17849                 :            :                                         act, &flow_err);
   17850         [ #  # ]:          0 :                                 if (ret < 0)
   17851                 :          0 :                                         return -rte_mtr_error_set(error,
   17852                 :            :                                           ENOTSUP,
   17853                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17854                 :            :                                           NULL, "Fail to save "
   17855                 :            :                                           "rss action into policy struct");
   17856                 :          0 :                                 act_cnt->fate_action =
   17857                 :            :                                         MLX5_FLOW_FATE_SHARED_RSS;
   17858                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_RSS;
   17859                 :          0 :                                 break;
   17860                 :            :                         }
   17861                 :          0 :                         case RTE_FLOW_ACTION_TYPE_PORT_ID:
   17862                 :            :                         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   17863                 :            :                         {
   17864                 :            :                                 struct mlx5_flow_dv_port_id_action_resource
   17865                 :            :                                         port_id_resource;
   17866                 :          0 :                                 uint32_t port_id = 0;
   17867                 :            : 
   17868         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17869                 :          0 :                                         return -rte_mtr_error_set(error,
   17870                 :            :                                         ENOTSUP,
   17871                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17872                 :            :                                         NULL, "cannot create policy "
   17873                 :            :                                         "port action for this color");
   17874                 :            :                                 memset(&port_id_resource, 0,
   17875                 :            :                                         sizeof(port_id_resource));
   17876         [ #  # ]:          0 :                                 if (flow_dv_translate_action_port_id(dev, act,
   17877                 :            :                                                 &port_id, &flow_err))
   17878                 :          0 :                                         return -rte_mtr_error_set(error,
   17879                 :            :                                         ENOTSUP,
   17880                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17881                 :            :                                         NULL, "cannot translate "
   17882                 :            :                                         "policy port action");
   17883                 :          0 :                                 port_id_resource.port_id = port_id;
   17884         [ #  # ]:          0 :                                 if (flow_dv_port_id_action_resource_register
   17885                 :            :                                         (dev, &port_id_resource,
   17886                 :            :                                         &dev_flow, &flow_err))
   17887                 :          0 :                                         return -rte_mtr_error_set(error,
   17888                 :            :                                         ENOTSUP,
   17889                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17890                 :            :                                         NULL, "cannot setup "
   17891                 :            :                                         "policy port action");
   17892                 :          0 :                                 act_cnt->rix_port_id_action =
   17893                 :          0 :                                         dev_flow.handle->rix_port_id_action;
   17894                 :          0 :                                 act_cnt->fate_action =
   17895                 :            :                                         MLX5_FLOW_FATE_PORT_ID;
   17896                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_PORT_ID;
   17897                 :          0 :                                 break;
   17898                 :            :                         }
   17899                 :          0 :                         case RTE_FLOW_ACTION_TYPE_JUMP:
   17900                 :            :                         {
   17901                 :            :                                 uint32_t jump_group = 0;
   17902                 :          0 :                                 uint32_t table = 0;
   17903                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl_data;
   17904                 :          0 :                                 struct flow_grp_info grp_info = {
   17905                 :          0 :                                         .external = !!dev_flow.external,
   17906                 :            :                                         .transfer = !!transfer,
   17907                 :          0 :                                         .fdb_def_rule = !!priv->fdb_def_rule,
   17908                 :            :                                         .std_tbl_fix = 0,
   17909                 :          0 :                                         .skip_scale = dev_flow.skip_scale &
   17910                 :            :                                         (1 << MLX5_SCALE_FLOW_GROUP_BIT),
   17911                 :            :                                 };
   17912                 :          0 :                                 struct mlx5_flow_meter_sub_policy *sub_policy =
   17913                 :          0 :                                         mtr_policy->sub_policys[domain][0];
   17914                 :            : 
   17915         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17916                 :          0 :                                         return -rte_mtr_error_set(error,
   17917                 :            :                                           ENOTSUP,
   17918                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17919                 :            :                                           NULL,
   17920                 :            :                                           "cannot create policy "
   17921                 :            :                                           "jump action for this color");
   17922                 :          0 :                                 jump_group =
   17923                 :            :                                 ((const struct rte_flow_action_jump *)
   17924                 :          0 :                                                         act->conf)->group;
   17925         [ #  # ]:          0 :                                 if (mlx5_flow_group_to_table(dev, NULL,
   17926                 :            :                                                        jump_group,
   17927                 :            :                                                        &table,
   17928                 :            :                                                        &grp_info, &flow_err))
   17929                 :          0 :                                         return -rte_mtr_error_set(error,
   17930                 :            :                                         ENOTSUP,
   17931                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17932                 :            :                                         NULL, "cannot setup "
   17933                 :            :                                         "policy jump action");
   17934                 :          0 :                                 sub_policy->jump_tbl[i] =
   17935                 :          0 :                                 mlx5_flow_dv_tbl_resource_get(dev,
   17936                 :            :                                                               table, egress,
   17937                 :            :                                                               transfer, !!dev_flow.external,
   17938                 :            :                                                               NULL, jump_group, 0,
   17939                 :            :                                                               0, &flow_err);
   17940                 :            :                                 if
   17941         [ #  # ]:          0 :                                 (!sub_policy->jump_tbl[i])
   17942                 :          0 :                                         return  -rte_mtr_error_set(error,
   17943                 :            :                                         ENOTSUP,
   17944                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17945                 :            :                                         NULL, "cannot create jump action.");
   17946                 :          0 :                                 tbl_data = container_of
   17947                 :            :                                 (sub_policy->jump_tbl[i],
   17948                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   17949                 :          0 :                                 act_cnt->dr_jump_action[domain] =
   17950                 :          0 :                                         tbl_data->jump.action;
   17951                 :          0 :                                 act_cnt->fate_action =
   17952                 :            :                                         MLX5_FLOW_FATE_JUMP;
   17953                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_JUMP;
   17954                 :          0 :                                 break;
   17955                 :            :                         }
   17956                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   17957                 :            :                         {
   17958         [ #  # ]:          0 :                                 if (i >= MLX5_MTR_RTE_COLORS)
   17959                 :          0 :                                         return -rte_mtr_error_set(error,
   17960                 :            :                                           ENOTSUP,
   17961                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   17962                 :            :                                           NULL,
   17963                 :            :                                           "cannot create policy modify field for this color");
   17964         [ #  # ]:          0 :                                 if (flow_dv_convert_action_modify_field
   17965                 :            :                                         (dev, mhdr_res, act, attr, &flow_err))
   17966                 :          0 :                                         return -rte_mtr_error_set(error,
   17967                 :            :                                         ENOTSUP,
   17968                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17969                 :            :                                         NULL, "cannot setup policy modify field action");
   17970         [ #  # ]:          0 :                                 if (!mhdr_res->actions_num)
   17971                 :          0 :                                         return -rte_mtr_error_set(error,
   17972                 :            :                                         ENOTSUP,
   17973                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   17974                 :            :                                         NULL, "cannot find policy modify field action");
   17975                 :          0 :                                 action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   17976                 :          0 :                                 break;
   17977                 :            :                         }
   17978                 :            :                         /*
   17979                 :            :                          * No need to check meter hierarchy for R colors
   17980                 :            :                          * here since it is done in the validation stage.
   17981                 :            :                          */
   17982                 :          0 :                         case RTE_FLOW_ACTION_TYPE_METER:
   17983                 :            :                         {
   17984                 :            :                                 const struct rte_flow_action_meter *mtr;
   17985                 :            :                                 struct mlx5_flow_meter_info *next_fm;
   17986                 :            :                                 struct mlx5_flow_meter_policy *next_policy;
   17987                 :            :                                 struct rte_flow_action tag_action;
   17988                 :            :                                 struct mlx5_rte_flow_action_set_tag set_tag;
   17989                 :          0 :                                 uint32_t next_mtr_idx = 0;
   17990                 :            : 
   17991                 :          0 :                                 mtr = act->conf;
   17992                 :          0 :                                 next_fm = mlx5_flow_meter_find(priv,
   17993                 :          0 :                                                         mtr->mtr_id,
   17994                 :            :                                                         &next_mtr_idx);
   17995         [ #  # ]:          0 :                                 if (!next_fm)
   17996                 :          0 :                                         return -rte_mtr_error_set(error, EINVAL,
   17997                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   17998                 :            :                                                 "Fail to find next meter.");
   17999         [ #  # ]:          0 :                                 if (next_fm->def_policy)
   18000                 :          0 :                                         return -rte_mtr_error_set(error, EINVAL,
   18001                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   18002                 :            :                                 "Hierarchy only supports termination meter.");
   18003                 :          0 :                                 next_policy = mlx5_flow_meter_policy_find(dev,
   18004                 :            :                                                 next_fm->policy_id, NULL);
   18005                 :            :                                 MLX5_ASSERT(next_policy);
   18006         [ #  # ]:          0 :                                 if (next_fm->drop_cnt) {
   18007                 :          0 :                                         set_tag.id =
   18008                 :          0 :                                                 (enum modify_reg)
   18009                 :          0 :                                                 mlx5_flow_get_reg_id(dev,
   18010                 :            :                                                 MLX5_MTR_ID,
   18011                 :            :                                                 0,
   18012                 :            :                                                 (struct rte_flow_error *)error);
   18013                 :          0 :                                         set_tag.offset = (priv->mtr_reg_share ?
   18014                 :          0 :                                                 MLX5_MTR_COLOR_BITS : 0);
   18015         [ #  # ]:          0 :                                         set_tag.length = (priv->mtr_reg_share ?
   18016                 :            :                                                MLX5_MTR_IDLE_BITS_IN_COLOR_REG :
   18017                 :            :                                                MLX5_REG_BITS);
   18018                 :          0 :                                         set_tag.data = next_mtr_idx;
   18019                 :          0 :                                         tag_action.type =
   18020                 :            :                                                 (enum rte_flow_action_type)
   18021                 :            :                                                 MLX5_RTE_FLOW_ACTION_TYPE_TAG;
   18022                 :          0 :                                         tag_action.conf = &set_tag;
   18023         [ #  # ]:          0 :                                         if (flow_dv_convert_action_set_reg
   18024                 :            :                                                 (mhdr_res, &tag_action,
   18025                 :            :                                                 (struct rte_flow_error *)error))
   18026                 :          0 :                                                 return -rte_errno;
   18027                 :          0 :                                         action_flags |=
   18028                 :            :                                                 MLX5_FLOW_ACTION_SET_TAG;
   18029                 :            :                                 }
   18030   [ #  #  #  # ]:          0 :                                 if (i == RTE_COLOR_YELLOW && next_fm->color_aware &&
   18031         [ #  # ]:          0 :                                     !next_fm->meter_action_y)
   18032         [ #  # ]:          0 :                                         if (__flow_dv_create_mtr_yellow_action(dev, next_fm, error))
   18033                 :          0 :                                                 return -rte_errno;
   18034                 :          0 :                                 act_cnt->fate_action = MLX5_FLOW_FATE_MTR;
   18035                 :          0 :                                 act_cnt->next_mtr_id = next_fm->meter_id;
   18036                 :          0 :                                 act_cnt->next_sub_policy = NULL;
   18037                 :          0 :                                 mtr_policy->is_hierarchy = 1;
   18038         [ #  # ]:          0 :                                 if (next_policy->mark)
   18039                 :          0 :                                         mtr_policy->mark = 1;
   18040                 :          0 :                                 mtr_policy->hierarchy_match_port =
   18041                 :          0 :                                                         next_policy->hierarchy_match_port;
   18042                 :          0 :                                 action_flags |=
   18043                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
   18044                 :          0 :                                 break;
   18045                 :            :                         }
   18046                 :            :                         default:
   18047                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   18048                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   18049                 :            :                                           NULL, "action type not supported");
   18050                 :            :                         }
   18051         [ #  # ]:          0 :                         if ((action_flags & MLX5_FLOW_ACTION_SET_TAG) ||
   18052                 :            :                             (action_flags & MLX5_FLOW_ACTION_MODIFY_FIELD)) {
   18053                 :            :                                 /* create modify action if needed. */
   18054                 :          0 :                                 dev_flow.dv.group = 1;
   18055         [ #  # ]:          0 :                                 if (flow_dv_modify_hdr_resource_register
   18056                 :            :                                         (dev, mhdr_res, &dev_flow, &flow_err))
   18057                 :          0 :                                         return -rte_mtr_error_set(error,
   18058                 :            :                                                 ENOTSUP,
   18059                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   18060                 :            :                                                 NULL, "cannot register policy set tag/modify field action");
   18061                 :          0 :                                 act_cnt->modify_hdr =
   18062                 :          0 :                                         dev_flow.handle->dvh.modify_hdr;
   18063                 :            :                         }
   18064                 :            :                 }
   18065                 :            :         }
   18066                 :            :         return 0;
   18067                 :            : }
   18068                 :            : 
   18069                 :            : /**
   18070                 :            :  * Create policy action per domain, lock free,
   18071                 :            :  * (mutex should be acquired by caller).
   18072                 :            :  * Dispatcher for action type specific call.
   18073                 :            :  *
   18074                 :            :  * @param[in] dev
   18075                 :            :  *   Pointer to the Ethernet device structure.
   18076                 :            :  * @param[in] mtr_policy
   18077                 :            :  *   Meter policy struct.
   18078                 :            :  * @param[in] action
   18079                 :            :  *   Action specification used to create meter actions.
   18080                 :            :  * @param[in] attr
   18081                 :            :  *   Pointer to the flow attributes.
   18082                 :            :  * @param[out] error
   18083                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   18084                 :            :  *   error only.
   18085                 :            :  *
   18086                 :            :  * @return
   18087                 :            :  *   0 on success, otherwise negative errno value.
   18088                 :            :  */
   18089                 :            : static int
   18090                 :          0 : flow_dv_create_mtr_policy_acts(struct rte_eth_dev *dev,
   18091                 :            :                       struct mlx5_flow_meter_policy *mtr_policy,
   18092                 :            :                       const struct rte_flow_action *actions[RTE_COLORS],
   18093                 :            :                       struct rte_flow_attr *attr,
   18094                 :            :                       struct rte_mtr_error *error)
   18095                 :            : {
   18096                 :            :         int ret, i;
   18097                 :            :         uint16_t sub_policy_num;
   18098                 :            : 
   18099         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18100                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   18101                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   18102                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18103         [ #  # ]:          0 :                 if (sub_policy_num) {
   18104                 :          0 :                         ret = __flow_dv_create_domain_policy_acts(dev,
   18105                 :            :                                 mtr_policy, actions, attr,
   18106                 :            :                                 (enum mlx5_meter_domain)i, error);
   18107                 :            :                         /* Cleaning resource is done in the caller level. */
   18108         [ #  # ]:          0 :                         if (ret)
   18109                 :          0 :                                 return ret;
   18110                 :            :                 }
   18111                 :            :         }
   18112                 :            :         return 0;
   18113                 :            : }
   18114                 :            : 
   18115                 :            : /**
   18116                 :            :  * Query a DV flow rule for its statistics via DevX.
   18117                 :            :  *
   18118                 :            :  * @param[in] dev
   18119                 :            :  *   Pointer to Ethernet device.
   18120                 :            :  * @param[in] cnt_idx
   18121                 :            :  *   Index to the flow counter.
   18122                 :            :  * @param[out] data
   18123                 :            :  *   Data retrieved by the query.
   18124                 :            :  * @param[out] error
   18125                 :            :  *   Perform verbose error reporting if not NULL.
   18126                 :            :  *
   18127                 :            :  * @return
   18128                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   18129                 :            :  */
   18130                 :            : static int
   18131                 :          0 : flow_dv_query_count(struct rte_eth_dev *dev, uint32_t cnt_idx, void *data,
   18132                 :            :                     struct rte_flow_error *error)
   18133                 :            : {
   18134                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18135                 :            :         struct rte_flow_query_count *qc = data;
   18136                 :            : 
   18137         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
   18138                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   18139                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18140                 :            :                                           NULL,
   18141                 :            :                                           "counters are not supported");
   18142         [ #  # ]:          0 :         if (cnt_idx) {
   18143                 :            :                 uint64_t pkts, bytes;
   18144                 :            :                 struct mlx5_flow_counter *cnt;
   18145                 :          0 :                 int err = _flow_dv_query_count(dev, cnt_idx, &pkts, &bytes);
   18146                 :            : 
   18147         [ #  # ]:          0 :                 if (err)
   18148                 :          0 :                         return rte_flow_error_set(error, -err,
   18149                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18150                 :            :                                         NULL, "cannot read counters");
   18151                 :            :                 cnt = flow_dv_counter_get_by_idx(dev, cnt_idx, NULL);
   18152                 :          0 :                 qc->hits_set = 1;
   18153                 :          0 :                 qc->bytes_set = 1;
   18154                 :          0 :                 qc->hits = pkts - cnt->hits;
   18155                 :          0 :                 qc->bytes = bytes - cnt->bytes;
   18156         [ #  # ]:          0 :                 if (qc->reset) {
   18157                 :          0 :                         cnt->hits = pkts;
   18158                 :          0 :                         cnt->bytes = bytes;
   18159                 :            :                 }
   18160                 :          0 :                 return 0;
   18161                 :            :         }
   18162                 :          0 :         return rte_flow_error_set(error, EINVAL,
   18163                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18164                 :            :                                   NULL,
   18165                 :            :                                   "counters are not available");
   18166                 :            : }
   18167                 :            : 
   18168                 :            : int
   18169                 :          0 : mlx5_flow_dv_action_query(struct rte_eth_dev *dev,
   18170                 :            :                           const struct rte_flow_action_handle *handle, void *data,
   18171                 :            :                           struct rte_flow_error *error)
   18172                 :            : {
   18173                 :            :         struct mlx5_age_param *age_param;
   18174                 :            :         struct rte_flow_query_age *resp;
   18175                 :          0 :         uint32_t act_idx = (uint32_t)(uintptr_t)handle;
   18176                 :          0 :         uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET;
   18177                 :          0 :         uint32_t idx = act_idx & ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
   18178                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18179                 :            :         struct mlx5_aso_ct_action *ct;
   18180                 :            :         uint16_t owner;
   18181                 :            :         uint32_t dev_idx;
   18182                 :            : 
   18183   [ #  #  #  # ]:          0 :         switch (type) {
   18184                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_AGE:
   18185                 :          0 :                 age_param = &mlx5_flow_aso_age_get_by_idx(dev, idx)->age_params;
   18186                 :            :                 resp = data;
   18187                 :          0 :                 resp->aged = rte_atomic_load_explicit(&age_param->state,
   18188                 :            :                                               rte_memory_order_relaxed) == AGE_TMOUT ?
   18189                 :          0 :                                                                           1 : 0;
   18190                 :          0 :                 resp->sec_since_last_hit_valid = !resp->aged;
   18191         [ #  # ]:          0 :                 if (resp->sec_since_last_hit_valid)
   18192                 :          0 :                         resp->sec_since_last_hit = rte_atomic_load_explicit
   18193                 :            :                              (&age_param->sec_since_last_hit, rte_memory_order_relaxed);
   18194                 :            :                 return 0;
   18195                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_COUNT:
   18196                 :          0 :                 return flow_dv_query_count(dev, idx, data, error);
   18197                 :          0 :         case MLX5_INDIRECT_ACTION_TYPE_CT:
   18198                 :          0 :                 owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(idx);
   18199         [ #  # ]:          0 :                 if (owner != PORT_ID(priv))
   18200                 :          0 :                         return rte_flow_error_set(error, EACCES,
   18201                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18202                 :            :                                         NULL,
   18203                 :            :                                         "CT object owned by another port");
   18204                 :          0 :                 dev_idx = MLX5_INDIRECT_ACT_CT_GET_IDX(idx);
   18205                 :          0 :                 ct = flow_aso_ct_get_by_dev_idx(dev, dev_idx);
   18206                 :            :                 MLX5_ASSERT(ct);
   18207         [ #  # ]:          0 :                 if (!ct->refcnt)
   18208                 :          0 :                         return rte_flow_error_set(error, EFAULT,
   18209                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18210                 :            :                                         NULL,
   18211                 :            :                                         "CT object is inactive");
   18212                 :          0 :                 ((struct rte_flow_action_conntrack *)data)->peer_port =
   18213                 :          0 :                                                         ct->peer;
   18214                 :          0 :                 ((struct rte_flow_action_conntrack *)data)->is_original_dir =
   18215                 :          0 :                                                         ct->is_original;
   18216         [ #  # ]:          0 :                 if (mlx5_aso_ct_query_by_wqe(priv->sh, MLX5_HW_INV_QUEUE, ct,
   18217                 :            :                                         data, NULL, true))
   18218                 :          0 :                         return rte_flow_error_set(error, EIO,
   18219                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18220                 :            :                                         NULL,
   18221                 :            :                                         "Failed to query CT context");
   18222                 :            :                 return 0;
   18223                 :          0 :         default:
   18224                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
   18225                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   18226                 :            :                                           "action type query not supported");
   18227                 :            :         }
   18228                 :            : }
   18229                 :            : 
   18230                 :            : /**
   18231                 :            :  * Query a flow rule AGE action for aging information.
   18232                 :            :  *
   18233                 :            :  * @param[in] dev
   18234                 :            :  *   Pointer to Ethernet device.
   18235                 :            :  * @param[in] flow
   18236                 :            :  *   Pointer to the sub flow.
   18237                 :            :  * @param[out] data
   18238                 :            :  *   data retrieved by the query.
   18239                 :            :  * @param[out] error
   18240                 :            :  *   Perform verbose error reporting if not NULL.
   18241                 :            :  *
   18242                 :            :  * @return
   18243                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   18244                 :            :  */
   18245                 :            : static int
   18246                 :          0 : flow_dv_query_age(struct rte_eth_dev *dev, struct rte_flow *flow,
   18247                 :            :                   void *data, struct rte_flow_error *error)
   18248                 :            : {
   18249                 :            :         struct rte_flow_query_age *resp = data;
   18250                 :            :         struct mlx5_age_param *age_param;
   18251                 :            : 
   18252         [ #  # ]:          0 :         if (flow->age) {
   18253                 :            :                 struct mlx5_aso_age_action *act =
   18254                 :          0 :                                      mlx5_flow_aso_age_get_by_idx(dev, flow->age);
   18255                 :            : 
   18256                 :          0 :                 age_param = &act->age_params;
   18257         [ #  # ]:          0 :         } else if (flow->counter) {
   18258                 :            :                 age_param = flow_dv_counter_idx_get_age(dev, flow->counter);
   18259                 :            : 
   18260         [ #  # ]:          0 :                 if (!age_param || !age_param->timeout)
   18261                 :          0 :                         return rte_flow_error_set
   18262                 :            :                                         (error, EINVAL,
   18263                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18264                 :            :                                          NULL, "cannot read age data");
   18265                 :            :         } else {
   18266                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   18267                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   18268                 :            :                                           NULL, "age data not available");
   18269                 :            :         }
   18270                 :          0 :         resp->aged = rte_atomic_load_explicit(&age_param->state, rte_memory_order_relaxed) ==
   18271                 :          0 :                                      AGE_TMOUT ? 1 : 0;
   18272                 :          0 :         resp->sec_since_last_hit_valid = !resp->aged;
   18273         [ #  # ]:          0 :         if (resp->sec_since_last_hit_valid)
   18274                 :          0 :                 resp->sec_since_last_hit = rte_atomic_load_explicit
   18275                 :            :                              (&age_param->sec_since_last_hit, rte_memory_order_relaxed);
   18276                 :            :         return 0;
   18277                 :            : }
   18278                 :            : 
   18279                 :            : /**
   18280                 :            :  * Query a flow.
   18281                 :            :  *
   18282                 :            :  * @see rte_flow_query()
   18283                 :            :  * @see rte_flow_ops
   18284                 :            :  */
   18285                 :            : static int
   18286                 :          0 : flow_dv_query(struct rte_eth_dev *dev,
   18287                 :            :               struct rte_flow *flow __rte_unused,
   18288                 :            :               const struct rte_flow_action *actions __rte_unused,
   18289                 :            :               void *data __rte_unused,
   18290                 :            :               struct rte_flow_error *error __rte_unused)
   18291                 :            : {
   18292                 :            :         int ret = -EINVAL;
   18293                 :            : 
   18294         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
   18295   [ #  #  #  # ]:          0 :                 switch (actions->type) {
   18296                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
   18297                 :            :                         break;
   18298                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
   18299                 :          0 :                         ret = flow_dv_query_count(dev, flow->counter, data,
   18300                 :            :                                                   error);
   18301                 :          0 :                         break;
   18302                 :          0 :                 case RTE_FLOW_ACTION_TYPE_AGE:
   18303         [ #  # ]:          0 :                         if (flow->indirect_type == MLX5_INDIRECT_ACTION_TYPE_CT)
   18304                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
   18305                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   18306                 :            :                                                   actions,
   18307                 :            :                                                   "age not available");
   18308                 :          0 :                         ret = flow_dv_query_age(dev, flow, data, error);
   18309                 :          0 :                         break;
   18310                 :          0 :                 default:
   18311                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
   18312                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
   18313                 :            :                                                   actions,
   18314                 :            :                                                   "action not supported");
   18315                 :            :                 }
   18316                 :            :         }
   18317                 :            :         return ret;
   18318                 :            : }
   18319                 :            : 
   18320                 :            : /**
   18321                 :            :  * Destroy the meter table set.
   18322                 :            :  * Lock free, (mutex should be acquired by caller).
   18323                 :            :  *
   18324                 :            :  * @param[in] dev
   18325                 :            :  *   Pointer to Ethernet device.
   18326                 :            :  * @param[in] fm
   18327                 :            :  *   Meter information table.
   18328                 :            :  */
   18329                 :            : static void
   18330                 :          0 : flow_dv_destroy_mtr_tbls(struct rte_eth_dev *dev,
   18331                 :            :                         struct mlx5_flow_meter_info *fm)
   18332                 :            : {
   18333                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18334                 :            :         int i;
   18335                 :            : 
   18336   [ #  #  #  # ]:          0 :         if (!fm || !priv->sh->config.dv_flow_en)
   18337                 :            :                 return;
   18338         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18339         [ #  # ]:          0 :                 if (fm->drop_rule[i]) {
   18340                 :            :                         claim_zero(mlx5_flow_os_destroy_flow(fm->drop_rule[i]));
   18341                 :          0 :                         fm->drop_rule[i] = NULL;
   18342                 :            :                 }
   18343                 :            :         }
   18344                 :            : }
   18345                 :            : 
   18346                 :            : static void
   18347                 :          0 : flow_dv_destroy_mtr_drop_tbls(struct rte_eth_dev *dev)
   18348                 :            : {
   18349                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18350                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18351                 :            :         struct mlx5_flow_tbl_data_entry *tbl;
   18352                 :            :         int i, j;
   18353                 :            : 
   18354         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18355         [ #  # ]:          0 :                 if (mtrmng->def_rule[i]) {
   18356                 :            :                         claim_zero(mlx5_flow_os_destroy_flow
   18357                 :            :                                         (mtrmng->def_rule[i]));
   18358                 :          0 :                         mtrmng->def_rule[i] = NULL;
   18359                 :            :                 }
   18360         [ #  # ]:          0 :                 if (mtrmng->def_matcher[i]) {
   18361                 :          0 :                         tbl = container_of(mtrmng->def_matcher[i]->tbl,
   18362                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   18363                 :          0 :                         mlx5_list_unregister(tbl->matchers,
   18364                 :            :                                              &mtrmng->def_matcher[i]->entry);
   18365                 :          0 :                         mtrmng->def_matcher[i] = NULL;
   18366                 :            :                 }
   18367         [ #  # ]:          0 :                 for (j = 0; j < MLX5_REG_BITS; j++) {
   18368         [ #  # ]:          0 :                         if (mtrmng->drop_matcher[i][j]) {
   18369                 :            :                                 tbl =
   18370                 :          0 :                                 container_of(mtrmng->drop_matcher[i][j]->tbl,
   18371                 :            :                                              struct mlx5_flow_tbl_data_entry,
   18372                 :            :                                              tbl);
   18373                 :          0 :                                 mlx5_list_unregister(tbl->matchers,
   18374                 :            :                                             &mtrmng->drop_matcher[i][j]->entry);
   18375                 :          0 :                                 mtrmng->drop_matcher[i][j] = NULL;
   18376                 :            :                         }
   18377                 :            :                 }
   18378         [ #  # ]:          0 :                 if (mtrmng->drop_tbl[i]) {
   18379                 :          0 :                         mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), mtrmng->drop_tbl[i]);
   18380                 :          0 :                         mtrmng->drop_tbl[i] = NULL;
   18381                 :            :                 }
   18382                 :            :         }
   18383                 :          0 : }
   18384                 :            : 
   18385                 :            : /* Number of meter flow actions, count and jump or count and drop. */
   18386                 :            : #define METER_ACTIONS 2
   18387                 :            : 
   18388                 :            : static void
   18389                 :          0 : __flow_dv_destroy_domain_def_policy(struct rte_eth_dev *dev,
   18390                 :            :                                     enum mlx5_meter_domain domain)
   18391                 :            : {
   18392                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18393                 :          0 :         struct mlx5_flow_meter_def_policy *def_policy =
   18394                 :          0 :                         priv->sh->mtrmng->def_policy[domain];
   18395                 :            : 
   18396                 :          0 :         __flow_dv_destroy_sub_policy_rules(dev, &def_policy->sub_policy);
   18397                 :          0 :         mlx5_free(def_policy);
   18398                 :          0 :         priv->sh->mtrmng->def_policy[domain] = NULL;
   18399                 :          0 : }
   18400                 :            : 
   18401                 :            : /**
   18402                 :            :  * Destroy the default policy table set.
   18403                 :            :  *
   18404                 :            :  * @param[in] dev
   18405                 :            :  *   Pointer to Ethernet device.
   18406                 :            :  */
   18407                 :            : static void
   18408                 :          0 : flow_dv_destroy_def_policy(struct rte_eth_dev *dev)
   18409                 :            : {
   18410                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18411                 :            :         int i;
   18412                 :            : 
   18413         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++)
   18414         [ #  # ]:          0 :                 if (priv->sh->mtrmng->def_policy[i])
   18415                 :          0 :                         __flow_dv_destroy_domain_def_policy(dev,
   18416                 :            :                                         (enum mlx5_meter_domain)i);
   18417                 :          0 :         priv->sh->mtrmng->def_policy_id = MLX5_INVALID_POLICY_ID;
   18418                 :          0 : }
   18419                 :            : 
   18420                 :            : static int
   18421                 :          0 : __flow_dv_create_policy_flow(struct rte_eth_dev *dev,
   18422                 :            :                         uint32_t color_reg_c_idx,
   18423                 :            :                         enum rte_color color, struct mlx5_flow_dv_matcher *matcher,
   18424                 :            :                         int actions_n, void *actions,
   18425                 :            :                         bool match_src_port, const struct rte_flow_item *item,
   18426                 :            :                         void **rule, const struct rte_flow_attr *attr)
   18427                 :            : {
   18428                 :            :         int ret;
   18429                 :          0 :         struct mlx5_flow_dv_match_params value = {
   18430                 :            :                 .size = sizeof(value.buf),
   18431                 :            :         };
   18432                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18433                 :            :         uint8_t misc_mask;
   18434                 :            : 
   18435   [ #  #  #  # ]:          0 :         if (match_src_port && priv->sh->esw_mode) {
   18436   [ #  #  #  # ]:          0 :                 if (item && item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT)
   18437                 :          0 :                         ret = flow_dv_translate_item_represented_port(dev, value.buf,
   18438                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_V);
   18439   [ #  #  #  # ]:          0 :                 else if (item && item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
   18440                 :          0 :                         ret = flow_dv_translate_item_port_representor(dev, value.buf,
   18441                 :            :                                                                       MLX5_SET_MATCHER_SW_V);
   18442                 :            :                 else
   18443                 :          0 :                         ret = flow_dv_translate_item_port_id(dev, value.buf,
   18444                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_V);
   18445         [ #  # ]:          0 :                 if (ret) {
   18446                 :          0 :                         DRV_LOG(ERR, "Failed to create meter policy%d flow's"
   18447                 :            :                                 " value with port.", color);
   18448                 :          0 :                         return -1;
   18449                 :            :                 }
   18450                 :            :         }
   18451                 :          0 :         flow_dv_match_meta_reg(value.buf, (enum modify_reg)color_reg_c_idx,
   18452                 :            :                                rte_col_2_mlx5_col(color), UINT32_MAX);
   18453         [ #  # ]:          0 :         misc_mask = flow_dv_matcher_enable(matcher->mask.buf);
   18454                 :            :         __flow_dv_adjust_buf_size(&value.size, misc_mask);
   18455                 :          0 :         ret = mlx5_flow_os_create_flow(matcher->matcher_object, (void *)&value,
   18456                 :            :                                        actions_n, actions, rule);
   18457                 :            :         if (ret) {
   18458                 :          0 :                 DRV_LOG(ERR, "Failed to create meter policy%d flow.", color);
   18459                 :          0 :                 return -1;
   18460                 :            :         }
   18461                 :            :         return 0;
   18462                 :            : }
   18463                 :            : 
   18464                 :            : static int
   18465                 :          0 : __flow_dv_create_policy_matcher(struct rte_eth_dev *dev,
   18466                 :            :                         uint32_t color_reg_c_idx,
   18467                 :            :                         uint16_t priority,
   18468                 :            :                         struct mlx5_flow_meter_sub_policy *sub_policy,
   18469                 :            :                         const struct rte_flow_attr *attr,
   18470                 :            :                         bool match_src_port,
   18471                 :            :                         const struct rte_flow_item *item,
   18472                 :            :                         struct mlx5_flow_dv_matcher **policy_matcher,
   18473                 :            :                         struct rte_flow_error *error)
   18474                 :            : {
   18475                 :            :         struct mlx5_list_entry *entry;
   18476                 :          0 :         struct mlx5_flow_tbl_resource *tbl_rsc = sub_policy->tbl_rsc;
   18477                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   18478                 :            :                 .mask = {
   18479                 :            :                         .size = sizeof(matcher.mask.buf),
   18480                 :            :                 },
   18481                 :            :                 .tbl = tbl_rsc,
   18482                 :            :         };
   18483                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   18484                 :            :                 .error = error,
   18485                 :            :                 .data = &matcher,
   18486                 :            :         };
   18487                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18488                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18489                 :            :         const uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
   18490                 :            :         int ret;
   18491                 :            : 
   18492   [ #  #  #  # ]:          0 :         if (match_src_port && priv->sh->esw_mode) {
   18493   [ #  #  #  # ]:          0 :                 if (item && item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT)
   18494                 :          0 :                         ret = flow_dv_translate_item_represented_port(dev, matcher.mask.buf,
   18495                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_M);
   18496   [ #  #  #  # ]:          0 :                 else if (item && item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
   18497                 :          0 :                         ret = flow_dv_translate_item_port_representor(dev, matcher.mask.buf,
   18498                 :            :                                                                       MLX5_SET_MATCHER_SW_M);
   18499                 :            :                 else
   18500                 :          0 :                         ret = flow_dv_translate_item_port_id(dev, matcher.mask.buf,
   18501                 :            :                                                 item, attr, MLX5_SET_MATCHER_SW_M);
   18502         [ #  # ]:          0 :                 if (ret) {
   18503                 :          0 :                         DRV_LOG(ERR, "Failed to register meter policy%d matcher"
   18504                 :            :                                 " with port.", priority);
   18505                 :          0 :                         return -1;
   18506                 :            :                 }
   18507                 :            :         }
   18508                 :          0 :         tbl_data = container_of(tbl_rsc, struct mlx5_flow_tbl_data_entry, tbl);
   18509                 :          0 :         flow_dv_match_meta_reg(matcher.mask.buf,
   18510                 :            :                 (enum modify_reg)color_reg_c_idx, color_mask, color_mask);
   18511                 :          0 :         matcher.priority = priority;
   18512                 :          0 :         matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
   18513                 :            :                                     matcher.mask.size);
   18514                 :          0 :         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   18515         [ #  # ]:          0 :         if (!entry) {
   18516                 :          0 :                 DRV_LOG(ERR, "Failed to register meter drop matcher.");
   18517                 :          0 :                 return -1;
   18518                 :            :         }
   18519                 :          0 :         *policy_matcher =
   18520                 :            :                 container_of(entry, struct mlx5_flow_dv_matcher, entry);
   18521                 :          0 :         return 0;
   18522                 :            : }
   18523                 :            : 
   18524                 :            : /**
   18525                 :            :  * Create the policy rules per domain.
   18526                 :            :  *
   18527                 :            :  * @param[in] dev
   18528                 :            :  *   Pointer to Ethernet device.
   18529                 :            :  * @param[in] sub_policy
   18530                 :            :  *    Pointer to sub policy table..
   18531                 :            :  * @param[in] egress
   18532                 :            :  *   Direction of the table.
   18533                 :            :  * @param[in] transfer
   18534                 :            :  *   E-Switch or NIC flow.
   18535                 :            :  * @param[in] acts
   18536                 :            :  *   Pointer to policy action list per color.
   18537                 :            :  *
   18538                 :            :  * @return
   18539                 :            :  *   0 on success, -1 otherwise.
   18540                 :            :  */
   18541                 :            : static int
   18542                 :          0 : __flow_dv_create_domain_policy_rules(struct rte_eth_dev *dev,
   18543                 :            :                 struct mlx5_flow_meter_sub_policy *sub_policy,
   18544                 :            :                 uint8_t egress, uint8_t transfer, bool *match_src_port,
   18545                 :            :                 struct mlx5_meter_policy_acts acts[RTE_COLORS])
   18546                 :            : {
   18547                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18548                 :            :         struct rte_flow_error flow_err;
   18549                 :            :         uint32_t color_reg_c_idx;
   18550                 :          0 :         struct rte_flow_attr attr = {
   18551                 :            :                 .group = MLX5_FLOW_TABLE_LEVEL_POLICY,
   18552                 :            :                 .priority = 0,
   18553                 :            :                 .ingress = 0,
   18554                 :          0 :                 .egress = !!egress,
   18555                 :          0 :                 .transfer = !!transfer,
   18556                 :            :                 .reserved = 0,
   18557                 :            :         };
   18558                 :            :         int i;
   18559                 :            :         uint16_t priority;
   18560                 :          0 :         int ret = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &flow_err);
   18561                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   18562                 :          0 :         struct mlx5_sub_policy_color_rule *tmp_rules[RTE_COLORS] = {NULL};
   18563                 :            : 
   18564         [ #  # ]:          0 :         if (ret < 0)
   18565                 :            :                 return -1;
   18566                 :            :         /* Create policy table with POLICY level. */
   18567         [ #  # ]:          0 :         if (!sub_policy->tbl_rsc)
   18568                 :          0 :                 sub_policy->tbl_rsc = mlx5_flow_dv_tbl_resource_get(dev,
   18569                 :            :                                                                     MLX5_FLOW_TABLE_LEVEL_POLICY,
   18570                 :            :                                                                     egress, transfer, false,
   18571                 :            :                                                                     NULL, 0, 0,
   18572                 :          0 :                                                                     sub_policy->idx, &flow_err);
   18573         [ #  # ]:          0 :         if (!sub_policy->tbl_rsc) {
   18574                 :          0 :                 DRV_LOG(ERR,
   18575                 :            :                         "Failed to create meter sub policy table.");
   18576                 :          0 :                 return -1;
   18577                 :            :         }
   18578                 :            :         /* Prepare matchers. */
   18579                 :          0 :         color_reg_c_idx = ret;
   18580         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   18581                 :          0 :                 TAILQ_INIT(&sub_policy->color_rules[i]);
   18582         [ #  # ]:          0 :                 if (!acts[i].actions_n)
   18583                 :          0 :                         continue;
   18584                 :          0 :                 color_rule = mlx5_malloc(MLX5_MEM_ZERO,
   18585                 :            :                                 sizeof(struct mlx5_sub_policy_color_rule),
   18586                 :            :                                 0, SOCKET_ID_ANY);
   18587         [ #  # ]:          0 :                 if (!color_rule) {
   18588                 :          0 :                         DRV_LOG(ERR, "No memory to create color rule.");
   18589                 :          0 :                         goto err_exit;
   18590                 :            :                 }
   18591                 :          0 :                 tmp_rules[i] = color_rule;
   18592                 :          0 :                 TAILQ_INSERT_TAIL(&sub_policy->color_rules[i],
   18593                 :            :                                   color_rule, next_port);
   18594                 :          0 :                 color_rule->src_port = priv->representor_id;
   18595                 :          0 :                 priority = (match_src_port[i] == match_src_port[RTE_COLOR_GREEN]) ?
   18596                 :          0 :                            MLX5_MTR_POLICY_MATCHER_PRIO : (MLX5_MTR_POLICY_MATCHER_PRIO + 1);
   18597                 :            :                 /* Create matchers for colors. */
   18598         [ #  # ]:          0 :                 if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
   18599                 :            :                                 priority, sub_policy,
   18600                 :            :                                 &attr, match_src_port[i], NULL,
   18601                 :            :                                 &color_rule->matcher, &flow_err)) {
   18602                 :          0 :                         DRV_LOG(ERR, "Failed to create color%u matcher.", i);
   18603                 :          0 :                         goto err_exit;
   18604                 :            :                 }
   18605                 :            :                 /* Create flow, matching color. */
   18606         [ #  # ]:          0 :                 if (__flow_dv_create_policy_flow(dev,
   18607                 :            :                                 color_reg_c_idx, (enum rte_color)i,
   18608                 :            :                                 color_rule->matcher,
   18609                 :          0 :                                 acts[i].actions_n, acts[i].dv_actions,
   18610                 :          0 :                                 match_src_port[i], NULL, &color_rule->rule,
   18611                 :            :                                 &attr)) {
   18612                 :          0 :                         DRV_LOG(ERR, "Failed to create color%u rule.", i);
   18613                 :          0 :                         goto err_exit;
   18614                 :            :                 }
   18615                 :            :         }
   18616                 :            :         return 0;
   18617                 :            : err_exit:
   18618                 :            :         /* All the policy rules will be cleared. */
   18619                 :            :         do {
   18620                 :          0 :                 color_rule = tmp_rules[i];
   18621         [ #  # ]:          0 :                 if (color_rule) {
   18622         [ #  # ]:          0 :                         if (color_rule->rule)
   18623                 :            :                                 mlx5_flow_os_destroy_flow(color_rule->rule);
   18624         [ #  # ]:          0 :                         if (color_rule->matcher) {
   18625                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl =
   18626                 :          0 :                                         container_of(color_rule->matcher->tbl,
   18627                 :            :                                                      typeof(*tbl), tbl);
   18628                 :          0 :                                 mlx5_list_unregister(tbl->matchers,
   18629                 :            :                                                 &color_rule->matcher->entry);
   18630                 :            :                         }
   18631         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[i],
   18632                 :            :                                      color_rule, next_port);
   18633                 :          0 :                         mlx5_free(color_rule);
   18634                 :            :                 }
   18635         [ #  # ]:          0 :         } while (i--);
   18636                 :            :         return -1;
   18637                 :            : }
   18638                 :            : 
   18639                 :            : static int
   18640                 :          0 : __flow_dv_create_policy_acts_rules(struct rte_eth_dev *dev,
   18641                 :            :                         struct mlx5_flow_meter_policy *mtr_policy,
   18642                 :            :                         struct mlx5_flow_meter_sub_policy *sub_policy,
   18643                 :            :                         uint32_t domain)
   18644                 :            : {
   18645                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18646                 :            :         struct mlx5_meter_policy_acts acts[RTE_COLORS];
   18647                 :            :         struct mlx5_flow_dv_tag_resource *tag;
   18648                 :            :         struct mlx5_flow_dv_port_id_action_resource *port_action;
   18649                 :            :         struct mlx5_hrxq *hrxq;
   18650                 :          0 :         struct mlx5_flow_meter_info *next_fm[RTE_COLORS] = {NULL};
   18651                 :            :         struct mlx5_flow_meter_policy *next_policy;
   18652                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy;
   18653                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18654                 :            :         struct rte_flow_error error;
   18655                 :          0 :         uint8_t egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18656                 :          0 :         uint8_t transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18657   [ #  #  #  #  :          0 :         bool mtr_first = egress || (transfer && priv->representor_id != UINT16_MAX);
                   #  # ]
   18658                 :          0 :         bool match_src_port[RTE_COLORS] = {false};
   18659                 :            :         int i;
   18660                 :            : 
   18661                 :            :         /* If RSS or Queue, no previous actions / rules is created. */
   18662         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   18663                 :          0 :                 acts[i].actions_n = 0;
   18664         [ #  # ]:          0 :                 if (i == RTE_COLOR_RED) {
   18665                 :            :                         /* Only support drop on red. */
   18666                 :          0 :                         acts[i].dv_actions[0] =
   18667                 :          0 :                                 mtr_policy->dr_drop_action[domain];
   18668                 :          0 :                         acts[i].actions_n = 1;
   18669                 :          0 :                         continue;
   18670                 :            :                 }
   18671         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR) {
   18672                 :          0 :                         struct rte_flow_attr attr = {
   18673                 :            :                                 .transfer = transfer
   18674                 :            :                         };
   18675                 :            : 
   18676                 :          0 :                         next_fm[i] = mlx5_flow_meter_find(priv,
   18677                 :            :                                         mtr_policy->act_cnt[i].next_mtr_id,
   18678                 :            :                                         NULL);
   18679         [ #  # ]:          0 :                         if (!next_fm[i]) {
   18680                 :          0 :                                 DRV_LOG(ERR,
   18681                 :            :                                         "Failed to get next hierarchy meter.");
   18682                 :          0 :                                 goto err_exit;
   18683                 :            :                         }
   18684         [ #  # ]:          0 :                         if (mlx5_flow_meter_attach(priv, next_fm[i],
   18685                 :            :                                                    &attr, &error)) {
   18686                 :          0 :                                 DRV_LOG(ERR, "%s", error.message);
   18687                 :          0 :                                 next_fm[i] = NULL;
   18688                 :          0 :                                 goto err_exit;
   18689                 :            :                         }
   18690                 :            :                         /* Meter action must be the first for TX. */
   18691         [ #  # ]:          0 :                         if (mtr_first) {
   18692                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18693         [ #  # ]:          0 :                                         (next_fm[i]->color_aware && i == RTE_COLOR_YELLOW) ?
   18694         [ #  # ]:          0 :                                                 next_fm[i]->meter_action_y :
   18695                 :            :                                                 next_fm[i]->meter_action_g;
   18696                 :          0 :                                 acts[i].actions_n++;
   18697                 :            :                         }
   18698                 :            :                 }
   18699         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].rix_mark) {
   18700                 :          0 :                         tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG],
   18701                 :            :                                         mtr_policy->act_cnt[i].rix_mark);
   18702         [ #  # ]:          0 :                         if (!tag) {
   18703                 :          0 :                                 DRV_LOG(ERR, "Failed to find "
   18704                 :            :                                 "mark action for policy.");
   18705                 :          0 :                                 goto err_exit;
   18706                 :            :                         }
   18707                 :          0 :                         acts[i].dv_actions[acts[i].actions_n] = tag->action;
   18708                 :          0 :                         acts[i].actions_n++;
   18709                 :            :                 }
   18710         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].modify_hdr) {
   18711                 :          0 :                         acts[i].dv_actions[acts[i].actions_n] =
   18712                 :          0 :                                 mtr_policy->act_cnt[i].modify_hdr->action;
   18713                 :          0 :                         acts[i].actions_n++;
   18714                 :            :                 }
   18715         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action) {
   18716   [ #  #  #  #  :          0 :                         switch (mtr_policy->act_cnt[i].fate_action) {
                      # ]
   18717                 :          0 :                         case MLX5_FLOW_FATE_PORT_ID:
   18718                 :          0 :                                 port_action = mlx5_ipool_get
   18719                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_PORT_ID],
   18720                 :            :                                 mtr_policy->act_cnt[i].rix_port_id_action);
   18721         [ #  # ]:          0 :                                 if (!port_action) {
   18722                 :          0 :                                         DRV_LOG(ERR, "Failed to find "
   18723                 :            :                                                 "port action for policy.");
   18724                 :          0 :                                         goto err_exit;
   18725                 :            :                                 }
   18726                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18727                 :          0 :                                         port_action->action;
   18728                 :          0 :                                 acts[i].actions_n++;
   18729                 :          0 :                                 match_src_port[i] = true;
   18730                 :          0 :                                 break;
   18731                 :          0 :                         case MLX5_FLOW_FATE_DROP:
   18732                 :            :                         case MLX5_FLOW_FATE_JUMP:
   18733                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18734                 :          0 :                                 mtr_policy->act_cnt[i].dr_jump_action[domain];
   18735                 :          0 :                                 acts[i].actions_n++;
   18736                 :          0 :                                 break;
   18737                 :          0 :                         case MLX5_FLOW_FATE_SHARED_RSS:
   18738                 :            :                         case MLX5_FLOW_FATE_QUEUE:
   18739                 :          0 :                                 hrxq = mlx5_ipool_get
   18740                 :          0 :                                         (priv->sh->ipool[MLX5_IPOOL_HRXQ],
   18741                 :            :                                          sub_policy->rix_hrxq[i]);
   18742         [ #  # ]:          0 :                                 if (!hrxq) {
   18743                 :          0 :                                         DRV_LOG(ERR, "Failed to find "
   18744                 :            :                                                 "queue action for policy.");
   18745                 :          0 :                                         goto err_exit;
   18746                 :            :                                 }
   18747                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n] =
   18748                 :          0 :                                         hrxq->action;
   18749                 :          0 :                                 acts[i].actions_n++;
   18750                 :          0 :                                 break;
   18751                 :          0 :                         case MLX5_FLOW_FATE_MTR:
   18752         [ #  # ]:          0 :                                 if (!next_fm[i]) {
   18753                 :          0 :                                         DRV_LOG(ERR,
   18754                 :            :                                                 "No next hierarchy meter.");
   18755                 :          0 :                                         goto err_exit;
   18756                 :            :                                 }
   18757         [ #  # ]:          0 :                                 if (!mtr_first) {
   18758                 :          0 :                                         acts[i].dv_actions[acts[i].actions_n] =
   18759         [ #  # ]:          0 :                                                 (next_fm[i]->color_aware && i == RTE_COLOR_YELLOW) ?
   18760         [ #  # ]:          0 :                                                         next_fm[i]->meter_action_y :
   18761                 :            :                                                         next_fm[i]->meter_action_g;
   18762                 :          0 :                                         acts[i].actions_n++;
   18763                 :            :                                 }
   18764         [ #  # ]:          0 :                                 if (mtr_policy->act_cnt[i].next_sub_policy) {
   18765                 :            :                                         next_sub_policy =
   18766                 :            :                                         mtr_policy->act_cnt[i].next_sub_policy;
   18767                 :            :                                 } else {
   18768                 :            :                                         next_policy =
   18769                 :          0 :                                                 mlx5_flow_meter_policy_find(dev,
   18770                 :            :                                                                 next_fm[i]->policy_id, NULL);
   18771                 :            :                                         MLX5_ASSERT(next_policy);
   18772                 :          0 :                                         next_sub_policy =
   18773                 :          0 :                                         next_policy->sub_policys[domain][0];
   18774                 :            :                                 }
   18775                 :            :                                 tbl_data =
   18776                 :          0 :                                         container_of(next_sub_policy->tbl_rsc,
   18777                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18778                 :          0 :                                 acts[i].dv_actions[acts[i].actions_n++] =
   18779                 :          0 :                                                         tbl_data->jump.action;
   18780         [ #  # ]:          0 :                                 if (mtr_policy->act_cnt[i].modify_hdr)
   18781                 :          0 :                                         match_src_port[i] = !!transfer;
   18782                 :            :                                 break;
   18783                 :            :                         default:
   18784                 :            :                                 /*Queue action do nothing*/
   18785                 :            :                                 break;
   18786                 :            :                         }
   18787                 :            :                 }
   18788                 :            :         }
   18789         [ #  # ]:          0 :         if (__flow_dv_create_domain_policy_rules(dev, sub_policy,
   18790                 :            :                                 egress, transfer, match_src_port, acts)) {
   18791                 :          0 :                 DRV_LOG(ERR,
   18792                 :            :                         "Failed to create policy rules per domain.");
   18793                 :          0 :                 goto err_exit;
   18794                 :            :         }
   18795   [ #  #  #  # ]:          0 :         if (match_src_port[RTE_COLOR_GREEN] || match_src_port[RTE_COLOR_YELLOW]) {
   18796                 :          0 :                 mtr_policy->match_port = 1;
   18797                 :          0 :                 mtr_policy->hierarchy_match_port = 1;
   18798                 :            :         }
   18799                 :            :         return 0;
   18800                 :            : err_exit:
   18801         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++)
   18802         [ #  # ]:          0 :                 if (next_fm[i])
   18803                 :          0 :                         mlx5_flow_meter_detach(priv, next_fm[i]);
   18804                 :            :         return -1;
   18805                 :            : }
   18806                 :            : 
   18807                 :            : /**
   18808                 :            :  * Create the policy rules.
   18809                 :            :  *
   18810                 :            :  * @param[in] dev
   18811                 :            :  *   Pointer to Ethernet device.
   18812                 :            :  * @param[in,out] mtr_policy
   18813                 :            :  *   Pointer to meter policy table.
   18814                 :            :  *
   18815                 :            :  * @return
   18816                 :            :  *   0 on success, -1 otherwise.
   18817                 :            :  */
   18818                 :            : static int
   18819                 :          0 : flow_dv_create_policy_rules(struct rte_eth_dev *dev,
   18820                 :            :                              struct mlx5_flow_meter_policy *mtr_policy)
   18821                 :            : {
   18822                 :            :         int i;
   18823                 :            :         int ret = 0;
   18824                 :            :         uint16_t sub_policy_num;
   18825                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_push_thread_workspace();
   18826                 :            : 
   18827                 :            :         RTE_SET_USED(wks);
   18828         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18829                 :          0 :                 sub_policy_num = (mtr_policy->sub_policy_num >>
   18830                 :          0 :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i)) &
   18831                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   18832         [ #  # ]:          0 :                 if (!sub_policy_num)
   18833                 :          0 :                         continue;
   18834                 :            :                 /* Prepare actions list and create policy rules. */
   18835         [ #  # ]:          0 :                 if (__flow_dv_create_policy_acts_rules(dev, mtr_policy,
   18836                 :          0 :                         mtr_policy->sub_policys[i][0], i)) {
   18837                 :          0 :                         DRV_LOG(ERR, "Failed to create policy action "
   18838                 :            :                                 "list per domain.");
   18839                 :            :                         ret = -1;
   18840                 :          0 :                         goto exit;
   18841                 :            :                 }
   18842                 :            :         }
   18843                 :          0 : exit:
   18844                 :          0 :         mlx5_flow_pop_thread_workspace();
   18845                 :          0 :         return ret;
   18846                 :            : }
   18847                 :            : 
   18848                 :            : static int
   18849                 :          0 : __flow_dv_create_domain_def_policy(struct rte_eth_dev *dev, uint32_t domain)
   18850                 :            : {
   18851                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18852                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   18853                 :            :         struct mlx5_flow_meter_def_policy *def_policy;
   18854                 :            :         struct mlx5_flow_tbl_resource *jump_tbl;
   18855                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   18856                 :            :         uint8_t egress, transfer;
   18857                 :            :         struct rte_flow_error error;
   18858                 :            :         struct mlx5_meter_policy_acts acts[RTE_COLORS];
   18859                 :          0 :         bool match_src_port[RTE_COLORS] = {false};
   18860                 :            :         int ret;
   18861                 :            : 
   18862                 :          0 :         egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   18863                 :          0 :         transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   18864                 :          0 :         def_policy = mtrmng->def_policy[domain];
   18865         [ #  # ]:          0 :         if (!def_policy) {
   18866                 :          0 :                 def_policy = mlx5_malloc(MLX5_MEM_ZERO,
   18867                 :            :                         sizeof(struct mlx5_flow_meter_def_policy),
   18868                 :            :                         RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
   18869         [ #  # ]:          0 :                 if (!def_policy) {
   18870                 :          0 :                         DRV_LOG(ERR, "Failed to alloc default policy table.");
   18871                 :          0 :                         goto def_policy_error;
   18872                 :            :                 }
   18873                 :          0 :                 mtrmng->def_policy[domain] = def_policy;
   18874                 :            :                 /* Create the meter suffix table with SUFFIX level. */
   18875                 :          0 :                 jump_tbl = mlx5_flow_dv_tbl_resource_get(dev,
   18876                 :            :                                                          MLX5_FLOW_TABLE_LEVEL_METER,
   18877                 :            :                                                          egress, transfer, false, NULL, 0,
   18878                 :            :                                                          0, MLX5_MTR_TABLE_ID_SUFFIX, &error);
   18879         [ #  # ]:          0 :                 if (!jump_tbl) {
   18880                 :          0 :                         DRV_LOG(ERR,
   18881                 :            :                                 "Failed to create meter suffix table.");
   18882                 :          0 :                         goto def_policy_error;
   18883                 :            :                 }
   18884                 :          0 :                 def_policy->sub_policy.jump_tbl[RTE_COLOR_GREEN] = jump_tbl;
   18885                 :          0 :                 tbl_data = container_of(jump_tbl,
   18886                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18887                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_GREEN] =
   18888                 :          0 :                                                 tbl_data->jump.action;
   18889                 :          0 :                 acts[RTE_COLOR_GREEN].dv_actions[0] = tbl_data->jump.action;
   18890                 :          0 :                 acts[RTE_COLOR_GREEN].actions_n = 1;
   18891                 :            :                 /*
   18892                 :            :                  * YELLOW has the same default policy as GREEN does.
   18893                 :            :                  * G & Y share the same table and action. The 2nd time of table
   18894                 :            :                  * resource getting is just to update the reference count for
   18895                 :            :                  * the releasing stage.
   18896                 :            :                  */
   18897                 :          0 :                 jump_tbl = mlx5_flow_dv_tbl_resource_get(dev,
   18898                 :            :                                                          MLX5_FLOW_TABLE_LEVEL_METER,
   18899                 :            :                                                          egress, transfer, false, NULL, 0,
   18900                 :            :                                                          0, MLX5_MTR_TABLE_ID_SUFFIX, &error);
   18901         [ #  # ]:          0 :                 if (!jump_tbl) {
   18902                 :          0 :                         DRV_LOG(ERR,
   18903                 :            :                                 "Failed to get meter suffix table.");
   18904                 :          0 :                         goto def_policy_error;
   18905                 :            :                 }
   18906                 :          0 :                 def_policy->sub_policy.jump_tbl[RTE_COLOR_YELLOW] = jump_tbl;
   18907                 :          0 :                 tbl_data = container_of(jump_tbl,
   18908                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18909                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_YELLOW] =
   18910                 :          0 :                                                 tbl_data->jump.action;
   18911                 :          0 :                 acts[RTE_COLOR_YELLOW].dv_actions[0] = tbl_data->jump.action;
   18912                 :          0 :                 acts[RTE_COLOR_YELLOW].actions_n = 1;
   18913                 :            :                 /* Create jump action to the drop table. */
   18914         [ #  # ]:          0 :                 if (!mtrmng->drop_tbl[domain]) {
   18915                 :          0 :                         mtrmng->drop_tbl[domain] = mlx5_flow_dv_tbl_resource_get
   18916                 :            :                                                         (dev, MLX5_FLOW_TABLE_LEVEL_METER,
   18917                 :            :                                                          egress, transfer, false, NULL, 0,
   18918                 :            :                                                          0, MLX5_MTR_TABLE_ID_DROP, &error);
   18919         [ #  # ]:          0 :                         if (!mtrmng->drop_tbl[domain]) {
   18920                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter "
   18921                 :            :                                         "drop table for default policy.");
   18922                 :          0 :                                 goto def_policy_error;
   18923                 :            :                         }
   18924                 :            :                 }
   18925                 :            :                 /* all RED: unique Drop table for jump action. */
   18926                 :          0 :                 tbl_data = container_of(mtrmng->drop_tbl[domain],
   18927                 :            :                                         struct mlx5_flow_tbl_data_entry, tbl);
   18928                 :          0 :                 def_policy->dr_jump_action[RTE_COLOR_RED] =
   18929                 :          0 :                                                 tbl_data->jump.action;
   18930                 :          0 :                 acts[RTE_COLOR_RED].dv_actions[0] = tbl_data->jump.action;
   18931                 :          0 :                 acts[RTE_COLOR_RED].actions_n = 1;
   18932                 :            :                 /* Create default policy rules. */
   18933                 :          0 :                 ret = __flow_dv_create_domain_policy_rules(dev,
   18934                 :            :                                         &def_policy->sub_policy,
   18935                 :            :                                         egress, transfer, match_src_port, acts);
   18936         [ #  # ]:          0 :                 if (ret) {
   18937                 :          0 :                         DRV_LOG(ERR, "Failed to create default policy rules.");
   18938                 :          0 :                         goto def_policy_error;
   18939                 :            :                 }
   18940                 :            :         }
   18941                 :            :         return 0;
   18942                 :          0 : def_policy_error:
   18943                 :          0 :         __flow_dv_destroy_domain_def_policy(dev,
   18944                 :            :                                             (enum mlx5_meter_domain)domain);
   18945                 :          0 :         return -1;
   18946                 :            : }
   18947                 :            : 
   18948                 :            : /**
   18949                 :            :  * Create the default policy table set.
   18950                 :            :  *
   18951                 :            :  * @param[in] dev
   18952                 :            :  *   Pointer to Ethernet device.
   18953                 :            :  * @return
   18954                 :            :  *   0 on success, -1 otherwise.
   18955                 :            :  */
   18956                 :            : static int
   18957                 :          0 : flow_dv_create_def_policy(struct rte_eth_dev *dev)
   18958                 :            : {
   18959                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18960                 :            :         int i;
   18961                 :            : 
   18962                 :            :         /* Non-termination policy table. */
   18963         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   18964   [ #  #  #  # ]:          0 :                 if (!priv->sh->config.dv_esw_en &&
   18965                 :            :                     i == MLX5_MTR_DOMAIN_TRANSFER)
   18966                 :          0 :                         continue;
   18967         [ #  # ]:          0 :                 if (__flow_dv_create_domain_def_policy(dev, i)) {
   18968                 :          0 :                         DRV_LOG(ERR, "Failed to create default policy");
   18969                 :            :                         /* Rollback the created default policies for others. */
   18970                 :          0 :                         flow_dv_destroy_def_policy(dev);
   18971                 :          0 :                         return -1;
   18972                 :            :                 }
   18973                 :            :         }
   18974                 :            :         return 0;
   18975                 :            : }
   18976                 :            : 
   18977                 :            : /**
   18978                 :            :  * Create the needed meter tables.
   18979                 :            :  * Lock free, (mutex should be acquired by caller).
   18980                 :            :  *
   18981                 :            :  * @param[in] dev
   18982                 :            :  *   Pointer to Ethernet device.
   18983                 :            :  * @param[in] fm
   18984                 :            :  *   Meter information table.
   18985                 :            :  * @param[in] mtr_idx
   18986                 :            :  *   Meter index.
   18987                 :            :  * @param[in] domain_bitmap
   18988                 :            :  *   Domain bitmap.
   18989                 :            :  * @return
   18990                 :            :  *   0 on success, -1 otherwise.
   18991                 :            :  */
   18992                 :            : static int
   18993                 :          0 : flow_dv_create_mtr_tbls(struct rte_eth_dev *dev,
   18994                 :            :                         struct mlx5_flow_meter_info *fm,
   18995                 :            :                         uint32_t mtr_idx,
   18996                 :            :                         uint8_t domain_bitmap)
   18997                 :            : {
   18998                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   18999                 :          0 :         struct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;
   19000                 :            :         struct rte_flow_error error;
   19001                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   19002                 :            :         uint8_t egress, transfer;
   19003                 :            :         void *actions[METER_ACTIONS];
   19004                 :            :         int domain, ret, i;
   19005                 :            :         struct mlx5_flow_counter *cnt;
   19006                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19007                 :            :                 .size = sizeof(value.buf),
   19008                 :            :         };
   19009                 :          0 :         struct mlx5_flow_dv_match_params matcher_para = {
   19010                 :            :                 .size = sizeof(matcher_para.buf),
   19011                 :            :         };
   19012                 :          0 :         int mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
   19013                 :            :                                                      0, &error);
   19014                 :          0 :         uint32_t mtr_id_mask = (UINT32_C(1) << mtrmng->max_mtr_bits) - 1;
   19015                 :          0 :         uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
   19016                 :            :         struct mlx5_list_entry *entry;
   19017                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   19018                 :            :                 .mask = {
   19019                 :            :                         .size = sizeof(matcher.mask.buf),
   19020                 :            :                 },
   19021                 :            :         };
   19022                 :            :         struct mlx5_flow_dv_matcher *drop_matcher;
   19023                 :          0 :         struct mlx5_flow_cb_ctx ctx = {
   19024                 :            :                 .error = &error,
   19025                 :            :                 .data = &matcher,
   19026                 :            :         };
   19027                 :            :         uint8_t misc_mask;
   19028                 :            : 
   19029   [ #  #  #  # ]:          0 :         if (!priv->mtr_en || mtr_id_reg_c < 0) {
   19030                 :          0 :                 rte_errno = ENOTSUP;
   19031                 :          0 :                 return -1;
   19032                 :            :         }
   19033         [ #  # ]:          0 :         for (domain = 0; domain < MLX5_MTR_DOMAIN_MAX; domain++) {
   19034         [ #  # ]:          0 :                 if (!(domain_bitmap & (1 << domain)) ||
   19035   [ #  #  #  # ]:          0 :                         (mtrmng->def_rule[domain] && !fm->drop_cnt))
   19036                 :          0 :                         continue;
   19037                 :          0 :                 egress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;
   19038                 :          0 :                 transfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;
   19039                 :            :                 /* Create the drop table with METER DROP level. */
   19040         [ #  # ]:          0 :                 if (!mtrmng->drop_tbl[domain]) {
   19041                 :          0 :                         mtrmng->drop_tbl[domain] = mlx5_flow_dv_tbl_resource_get(dev,
   19042                 :            :                                                         MLX5_FLOW_TABLE_LEVEL_METER,
   19043                 :            :                                                         egress, transfer, false, NULL, 0,
   19044                 :            :                                                         0, MLX5_MTR_TABLE_ID_DROP, &error);
   19045         [ #  # ]:          0 :                         if (!mtrmng->drop_tbl[domain]) {
   19046                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter drop table.");
   19047                 :          0 :                                 goto policy_error;
   19048                 :            :                         }
   19049                 :            :                 }
   19050                 :            :                 /* Create default matcher in drop table. */
   19051                 :          0 :                 matcher.tbl = mtrmng->drop_tbl[domain];
   19052                 :          0 :                 tbl_data = container_of(mtrmng->drop_tbl[domain],
   19053                 :            :                                 struct mlx5_flow_tbl_data_entry, tbl);
   19054         [ #  # ]:          0 :                 if (!mtrmng->def_matcher[domain]) {
   19055                 :          0 :                         flow_dv_match_meta_reg_all(matcher.mask.buf, value.buf,
   19056                 :            :                                        (enum modify_reg)mtr_id_reg_c,
   19057                 :            :                                        0, 0);
   19058                 :          0 :                         matcher.priority = MLX5_MTRS_DEFAULT_RULE_PRIORITY;
   19059                 :          0 :                         matcher.crc = rte_raw_cksum
   19060                 :            :                                         ((const void *)matcher.mask.buf,
   19061                 :            :                                         matcher.mask.size);
   19062                 :          0 :                         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   19063         [ #  # ]:          0 :                         if (!entry) {
   19064                 :          0 :                                 DRV_LOG(ERR, "Failed to register meter "
   19065                 :            :                                 "drop default matcher.");
   19066                 :          0 :                                 goto policy_error;
   19067                 :            :                         }
   19068                 :          0 :                         mtrmng->def_matcher[domain] = container_of(entry,
   19069                 :            :                         struct mlx5_flow_dv_matcher, entry);
   19070                 :            :                 }
   19071                 :            :                 /* Create default rule in drop table. */
   19072         [ #  # ]:          0 :                 if (!mtrmng->def_rule[domain]) {
   19073                 :            :                         i = 0;
   19074                 :          0 :                         actions[i++] = priv->sh->dr_drop_action;
   19075                 :          0 :                         flow_dv_match_meta_reg_all(matcher_para.buf, value.buf,
   19076                 :            :                                 (enum modify_reg)mtr_id_reg_c, 0, 0);
   19077         [ #  # ]:          0 :                         misc_mask = flow_dv_matcher_enable(mtrmng->def_matcher[domain]->mask.buf);
   19078                 :            :                         __flow_dv_adjust_buf_size(&value.size, misc_mask);
   19079                 :          0 :                         ret = mlx5_flow_os_create_flow
   19080                 :            :                                 (mtrmng->def_matcher[domain]->matcher_object,
   19081                 :            :                                 (void *)&value, i, actions,
   19082                 :            :                                 &mtrmng->def_rule[domain]);
   19083                 :            :                         if (ret) {
   19084                 :          0 :                                 DRV_LOG(ERR, "Failed to create meter "
   19085                 :            :                                 "default drop rule for drop table.");
   19086                 :          0 :                                 goto policy_error;
   19087                 :            :                         }
   19088                 :            :                 }
   19089         [ #  # ]:          0 :                 if (!fm->drop_cnt)
   19090                 :          0 :                         continue;
   19091                 :            :                 MLX5_ASSERT(mtrmng->max_mtr_bits);
   19092         [ #  # ]:          0 :                 if (!mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1]) {
   19093                 :            :                         /* Create matchers for Drop. */
   19094                 :          0 :                         flow_dv_match_meta_reg_all(matcher.mask.buf, value.buf,
   19095                 :            :                                         (enum modify_reg)mtr_id_reg_c, 0,
   19096                 :            :                                         (mtr_id_mask << mtr_id_offset));
   19097                 :          0 :                         matcher.priority = MLX5_REG_BITS - mtrmng->max_mtr_bits;
   19098                 :          0 :                         matcher.crc = rte_raw_cksum
   19099                 :            :                                         ((const void *)matcher.mask.buf,
   19100                 :            :                                         matcher.mask.size);
   19101                 :          0 :                         entry = mlx5_list_register(tbl_data->matchers, &ctx);
   19102         [ #  # ]:          0 :                         if (!entry) {
   19103                 :          0 :                                 DRV_LOG(ERR,
   19104                 :            :                                 "Failed to register meter drop matcher.");
   19105                 :          0 :                                 goto policy_error;
   19106                 :            :                         }
   19107                 :          0 :                         mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1] =
   19108                 :            :                                 container_of(entry, struct mlx5_flow_dv_matcher,
   19109                 :            :                                              entry);
   19110                 :            :                 }
   19111                 :          0 :                 drop_matcher =
   19112                 :          0 :                         mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1];
   19113                 :            :                 /* Create drop rule, matching meter_id only. */
   19114                 :          0 :                 flow_dv_match_meta_reg_all(matcher_para.buf, value.buf,
   19115                 :            :                                 (enum modify_reg)mtr_id_reg_c,
   19116                 :            :                                 (mtr_idx << mtr_id_offset), UINT32_MAX);
   19117                 :            :                 i = 0;
   19118         [ #  # ]:          0 :                 cnt = flow_dv_counter_get_by_idx(dev,
   19119                 :            :                                         fm->drop_cnt, NULL);
   19120                 :          0 :                 actions[i++] = cnt->action;
   19121                 :          0 :                 actions[i++] = priv->sh->dr_drop_action;
   19122         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(drop_matcher->mask.buf);
   19123                 :            :                 __flow_dv_adjust_buf_size(&value.size, misc_mask);
   19124                 :          0 :                 ret = mlx5_flow_os_create_flow(drop_matcher->matcher_object,
   19125                 :            :                                                (void *)&value, i, actions,
   19126                 :            :                                                &fm->drop_rule[domain]);
   19127                 :            :                 if (ret) {
   19128                 :          0 :                         DRV_LOG(ERR, "Failed to create meter "
   19129                 :            :                                 "drop rule for drop table.");
   19130                 :          0 :                                 goto policy_error;
   19131                 :            :                 }
   19132                 :            :         }
   19133                 :            :         return 0;
   19134                 :            : policy_error:
   19135         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {
   19136         [ #  # ]:          0 :                 if (fm->drop_rule[i]) {
   19137                 :            :                         claim_zero(mlx5_flow_os_destroy_flow
   19138                 :            :                                 (fm->drop_rule[i]));
   19139                 :          0 :                         fm->drop_rule[i] = NULL;
   19140                 :            :                 }
   19141                 :            :         }
   19142                 :            :         return -1;
   19143                 :            : }
   19144                 :            : 
   19145                 :            : static struct mlx5_flow_meter_sub_policy *
   19146                 :          0 : __flow_dv_meter_get_rss_sub_policy(struct rte_eth_dev *dev,
   19147                 :            :                 struct mlx5_flow_meter_policy *mtr_policy,
   19148                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS],
   19149                 :            :                 struct mlx5_flow_meter_sub_policy *next_sub_policy,
   19150                 :            :                 bool *is_reuse)
   19151                 :            : {
   19152                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19153                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   19154                 :          0 :         uint32_t sub_policy_idx = 0;
   19155                 :          0 :         uint32_t hrxq_idx[MLX5_MTR_RTE_COLORS] = {0};
   19156                 :            :         uint32_t i, j;
   19157                 :            :         struct mlx5_hrxq *hrxq;
   19158                 :            :         struct mlx5_flow_handle dh;
   19159                 :            :         struct mlx5_meter_policy_action_container *act_cnt;
   19160                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   19161                 :            :         uint16_t sub_policy_num;
   19162                 :          0 :         struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
   19163                 :            : 
   19164                 :            :         MLX5_ASSERT(wks);
   19165                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   19166         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19167         [ #  # ]:          0 :                 if (!rss_desc[i])
   19168                 :          0 :                         continue;
   19169                 :          0 :                 hrxq = mlx5_hrxq_get(dev, rss_desc[i]);
   19170         [ #  # ]:          0 :                 if (!hrxq) {
   19171                 :            :                         rte_spinlock_unlock(&mtr_policy->sl);
   19172                 :          0 :                         return NULL;
   19173                 :            :                 }
   19174                 :          0 :                 hrxq_idx[i] = hrxq->idx;
   19175                 :            :         }
   19176                 :          0 :         sub_policy_num = (mtr_policy->sub_policy_num >>
   19177                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19178                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19179         [ #  # ]:          0 :         for (j = 0; j < sub_policy_num; j++) {
   19180         [ #  # ]:          0 :                 for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19181         [ #  # ]:          0 :                         if (rss_desc[i] &&
   19182                 :          0 :                             hrxq_idx[i] !=
   19183         [ #  # ]:          0 :                             mtr_policy->sub_policys[domain][j]->rix_hrxq[i])
   19184                 :            :                                 break;
   19185                 :            :                 }
   19186         [ #  # ]:          0 :                 if (i >= MLX5_MTR_RTE_COLORS) {
   19187                 :            :                         /*
   19188                 :            :                          * Found the sub policy table with
   19189                 :            :                          * the same queue per color.
   19190                 :            :                          */
   19191                 :            :                         rte_spinlock_unlock(&mtr_policy->sl);
   19192         [ #  # ]:          0 :                         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++)
   19193                 :          0 :                                 mlx5_hrxq_release(dev, hrxq_idx[i]);
   19194                 :          0 :                         *is_reuse = true;
   19195                 :          0 :                         return mtr_policy->sub_policys[domain][j];
   19196                 :            :                 }
   19197                 :            :         }
   19198                 :            :         /* Create sub policy. */
   19199         [ #  # ]:          0 :         if (!mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_GREEN] &&
   19200                 :            :             !mtr_policy->sub_policys[domain][0]->rix_hrxq[RTE_COLOR_YELLOW]) {
   19201                 :            :                 /* Reuse the first pre-allocated sub_policy. */
   19202                 :            :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19203                 :          0 :                 sub_policy_idx = sub_policy->idx;
   19204                 :            :         } else {
   19205                 :          0 :                 sub_policy = mlx5_ipool_zmalloc
   19206                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19207                 :            :                                  &sub_policy_idx);
   19208         [ #  # ]:          0 :                 if (!sub_policy ||
   19209         [ #  # ]:          0 :                     sub_policy_idx > MLX5_MAX_SUB_POLICY_TBL_NUM) {
   19210         [ #  # ]:          0 :                         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++)
   19211                 :          0 :                                 mlx5_hrxq_release(dev, hrxq_idx[i]);
   19212                 :          0 :                         goto rss_sub_policy_error;
   19213                 :            :                 }
   19214                 :          0 :                 sub_policy->idx = sub_policy_idx;
   19215                 :          0 :                 sub_policy->main_policy = mtr_policy;
   19216                 :            :         }
   19217         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19218         [ #  # ]:          0 :                 if (!rss_desc[i])
   19219                 :          0 :                         continue;
   19220                 :          0 :                 sub_policy->rix_hrxq[i] = hrxq_idx[i];
   19221         [ #  # ]:          0 :                 if (mtr_policy->is_hierarchy) {
   19222                 :            :                         act_cnt = &mtr_policy->act_cnt[i];
   19223                 :          0 :                         act_cnt->next_sub_policy = next_sub_policy;
   19224                 :          0 :                         mlx5_hrxq_release(dev, hrxq_idx[i]);
   19225                 :            :                 } else {
   19226                 :            :                         /*
   19227                 :            :                          * Overwrite the last action from
   19228                 :            :                          * RSS action to Queue action.
   19229                 :            :                          */
   19230                 :          0 :                         hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
   19231                 :            :                                               hrxq_idx[i]);
   19232         [ #  # ]:          0 :                         if (!hrxq) {
   19233                 :          0 :                                 DRV_LOG(ERR, "Failed to get policy hrxq");
   19234                 :          0 :                                 goto rss_sub_policy_error;
   19235                 :            :                         }
   19236                 :            :                         act_cnt = &mtr_policy->act_cnt[i];
   19237   [ #  #  #  # ]:          0 :                         if (act_cnt->rix_mark || act_cnt->modify_hdr) {
   19238                 :            :                                 memset(&dh, 0, sizeof(struct mlx5_flow_handle));
   19239         [ #  # ]:          0 :                                 if (act_cnt->rix_mark)
   19240                 :          0 :                                         wks->mark = 1;
   19241                 :          0 :                                 dh.fate_action = MLX5_FLOW_FATE_QUEUE;
   19242                 :          0 :                                 dh.rix_hrxq = hrxq_idx[i];
   19243                 :          0 :                                 mlx5_flow_drv_rxq_flags_set(dev, &dh);
   19244                 :            :                         }
   19245                 :            :                 }
   19246                 :            :         }
   19247         [ #  # ]:          0 :         if (__flow_dv_create_policy_acts_rules(dev, mtr_policy,
   19248                 :            :                                                sub_policy, domain)) {
   19249                 :          0 :                 DRV_LOG(ERR, "Failed to create policy "
   19250                 :            :                         "rules for ingress domain.");
   19251                 :          0 :                 goto rss_sub_policy_error;
   19252                 :            :         }
   19253         [ #  # ]:          0 :         if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19254                 :          0 :                 i = (mtr_policy->sub_policy_num >>
   19255                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19256                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19257         [ #  # ]:          0 :                 if (i >= MLX5_MTR_RSS_MAX_SUB_POLICY) {
   19258                 :          0 :                         DRV_LOG(ERR, "No free sub-policy slot.");
   19259                 :          0 :                         goto rss_sub_policy_error;
   19260                 :            :                 }
   19261                 :          0 :                 mtr_policy->sub_policys[domain][i] = sub_policy;
   19262                 :          0 :                 i++;
   19263                 :          0 :                 mtr_policy->sub_policy_num &= ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19264                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain));
   19265                 :          0 :                 mtr_policy->sub_policy_num |=
   19266                 :          0 :                         (i & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19267                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain);
   19268                 :            :         }
   19269                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19270                 :          0 :         *is_reuse = false;
   19271                 :          0 :         return sub_policy;
   19272                 :          0 : rss_sub_policy_error:
   19273         [ #  # ]:          0 :         if (sub_policy) {
   19274                 :          0 :                 __flow_dv_destroy_sub_policy_rules(dev, sub_policy);
   19275         [ #  # ]:          0 :                 if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19276                 :          0 :                         i = (mtr_policy->sub_policy_num >>
   19277                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19278                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19279                 :          0 :                         mtr_policy->sub_policys[domain][i] = NULL;
   19280                 :          0 :                         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19281                 :          0 :                                         sub_policy->idx);
   19282                 :            :                 }
   19283                 :            :         }
   19284                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19285                 :          0 :         return NULL;
   19286                 :            : }
   19287                 :            : 
   19288                 :            : /**
   19289                 :            :  * Find the policy table for prefix table with RSS.
   19290                 :            :  *
   19291                 :            :  * @param[in] dev
   19292                 :            :  *   Pointer to Ethernet device.
   19293                 :            :  * @param[in] mtr_policy
   19294                 :            :  *   Pointer to meter policy table.
   19295                 :            :  * @param[in] rss_desc
   19296                 :            :  *   Pointer to rss_desc
   19297                 :            :  * @return
   19298                 :            :  *   Pointer to table set on success, NULL otherwise and rte_errno is set.
   19299                 :            :  */
   19300                 :            : static struct mlx5_flow_meter_sub_policy *
   19301                 :          0 : flow_dv_meter_sub_policy_rss_prepare(struct rte_eth_dev *dev,
   19302                 :            :                 struct mlx5_flow_meter_policy *mtr_policy,
   19303                 :            :                 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS])
   19304                 :            : {
   19305                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19306                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   19307                 :            :         struct mlx5_flow_meter_info *next_fm;
   19308                 :            :         struct mlx5_flow_meter_policy *next_policy;
   19309                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy = NULL;
   19310                 :            :         struct mlx5_flow_meter_policy *policies[MLX5_MTR_CHAIN_MAX_NUM];
   19311                 :            :         struct mlx5_flow_meter_sub_policy *sub_policies[MLX5_MTR_CHAIN_MAX_NUM];
   19312                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   19313                 :            :         bool reuse_sub_policy;
   19314                 :            :         uint32_t i = 0;
   19315                 :            :         uint32_t j = 0;
   19316                 :            : 
   19317                 :            :         while (true) {
   19318                 :            :                 /* Iterate hierarchy to get all policies in this hierarchy. */
   19319                 :          0 :                 policies[i++] = mtr_policy;
   19320         [ #  # ]:          0 :                 if (!mtr_policy->is_hierarchy)
   19321                 :            :                         break;
   19322         [ #  # ]:          0 :                 if (i >= MLX5_MTR_CHAIN_MAX_NUM) {
   19323                 :          0 :                         DRV_LOG(ERR, "Exceed max meter number in hierarchy.");
   19324                 :          0 :                         return NULL;
   19325                 :            :                 }
   19326                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19327                 :          0 :                 next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, mtr_policy, NULL);
   19328                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19329         [ #  # ]:          0 :                 if (!next_fm) {
   19330                 :          0 :                         DRV_LOG(ERR, "Failed to get next meter in hierarchy.");
   19331                 :          0 :                         return NULL;
   19332                 :            :                 }
   19333                 :            :                 next_policy =
   19334                 :          0 :                         mlx5_flow_meter_policy_find(dev, next_fm->policy_id,
   19335                 :            :                                                     NULL);
   19336                 :            :                 MLX5_ASSERT(next_policy);
   19337                 :            :                 mtr_policy = next_policy;
   19338                 :            :         }
   19339         [ #  # ]:          0 :         while (i) {
   19340                 :            :                 /**
   19341                 :            :                  * From last policy to the first one in hierarchy,
   19342                 :            :                  * create / get the sub policy for each of them.
   19343                 :            :                  */
   19344                 :          0 :                 sub_policy = __flow_dv_meter_get_rss_sub_policy(dev,
   19345                 :            :                                                         policies[--i],
   19346                 :            :                                                         rss_desc,
   19347                 :            :                                                         next_sub_policy,
   19348                 :            :                                                         &reuse_sub_policy);
   19349         [ #  # ]:          0 :                 if (!sub_policy) {
   19350                 :          0 :                         DRV_LOG(ERR, "Failed to get the sub policy.");
   19351                 :          0 :                         goto err_exit;
   19352                 :            :                 }
   19353         [ #  # ]:          0 :                 if (!reuse_sub_policy)
   19354                 :          0 :                         sub_policies[j++] = sub_policy;
   19355                 :            :                 next_sub_policy = sub_policy;
   19356                 :            :         }
   19357                 :            :         return sub_policy;
   19358                 :            : err_exit:
   19359         [ #  # ]:          0 :         while (j) {
   19360                 :            :                 uint16_t sub_policy_num;
   19361                 :            : 
   19362                 :          0 :                 sub_policy = sub_policies[--j];
   19363                 :          0 :                 mtr_policy = sub_policy->main_policy;
   19364                 :          0 :                 __flow_dv_destroy_sub_policy_rules(dev, sub_policy);
   19365         [ #  # ]:          0 :                 if (sub_policy != mtr_policy->sub_policys[domain][0]) {
   19366                 :          0 :                         sub_policy_num = (mtr_policy->sub_policy_num >>
   19367                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19368                 :            :                                 MLX5_MTR_SUB_POLICY_NUM_MASK;
   19369                 :          0 :                         mtr_policy->sub_policys[domain][sub_policy_num - 1] =
   19370                 :            :                                                                         NULL;
   19371                 :          0 :                         sub_policy_num--;
   19372                 :          0 :                         mtr_policy->sub_policy_num &=
   19373                 :          0 :                                 ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19374                 :          0 :                                   (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i));
   19375                 :          0 :                         mtr_policy->sub_policy_num |=
   19376                 :          0 :                         (sub_policy_num & MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19377                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * i);
   19378                 :          0 :                         mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19379                 :          0 :                                         sub_policy->idx);
   19380                 :            :                 }
   19381                 :            :         }
   19382                 :            :         return NULL;
   19383                 :            : }
   19384                 :            : 
   19385                 :            : /**
   19386                 :            :  * Check if need to create hierarchy tag rule.
   19387                 :            :  *
   19388                 :            :  * @param[in] priv
   19389                 :            :  *   Pointer to mlx5_priv.
   19390                 :            :  * @param[in] mtr_policy
   19391                 :            :  *   Pointer to current meter policy.
   19392                 :            :  * @param[in] src_port
   19393                 :            :  *   The src port this extra rule should use.
   19394                 :            :  * @param[out] next_fm
   19395                 :            :  *   Pointer to next meter in hierarchy.
   19396                 :            :  * @param[out] skip
   19397                 :            :  *   Indicate if skip the tag rule creation.
   19398                 :            :  * @param[out] error
   19399                 :            :  *   Perform verbose error reporting if not NULL.
   19400                 :            :  * @return
   19401                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19402                 :            :  */
   19403                 :            : static int
   19404                 :          0 : mlx5_meter_hierarchy_skip_tag_rule(struct mlx5_priv *priv,
   19405                 :            :                                    struct mlx5_flow_meter_policy *mtr_policy,
   19406                 :            :                                    int32_t src_port,
   19407                 :            :                                    struct mlx5_flow_meter_info **next_fm,
   19408                 :            :                                    bool *skip,
   19409                 :            :                                    struct rte_flow_error *error)
   19410                 :            : {
   19411                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   19412                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   19413                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_TRANSFER;
   19414                 :            :         int ret = 0;
   19415                 :            :         int i;
   19416                 :            : 
   19417                 :          0 :         *next_fm = NULL;
   19418                 :          0 :         *skip = false;
   19419                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   19420         [ #  # ]:          0 :         if (mtr_policy->is_hierarchy) {
   19421                 :          0 :                 *next_fm = mlx5_flow_meter_hierarchy_next_meter(priv, mtr_policy, NULL);
   19422         [ #  # ]:          0 :                 if (!*next_fm) {
   19423                 :          0 :                         ret = rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
   19424                 :            :                                                 NULL, "Failed to find next meter in hierarchy.");
   19425                 :          0 :                         goto exit;
   19426                 :            :                 }
   19427                 :            :         }
   19428         [ #  # ]:          0 :         if (!mtr_policy->match_port) {
   19429                 :          0 :                 *skip = true;
   19430                 :          0 :                 goto exit;
   19431                 :            :         }
   19432                 :          0 :         sub_policy = mtr_policy->sub_policys[domain][0];
   19433         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19434         [ #  # ]:          0 :                 if (mtr_policy->act_cnt[i].fate_action != MLX5_FLOW_FATE_MTR &&
   19435                 :            :                     mtr_policy->act_cnt[i].fate_action != MLX5_FLOW_FATE_PORT_ID)
   19436                 :          0 :                         continue;
   19437         [ #  # ]:          0 :                 TAILQ_FOREACH(color_rule, &sub_policy->color_rules[i], next_port)
   19438         [ #  # ]:          0 :                         if (color_rule->src_port == src_port) {
   19439                 :          0 :                                 *skip = true;
   19440                 :          0 :                                 goto exit;
   19441                 :            :                         }
   19442                 :            :         }
   19443                 :          0 : exit:
   19444                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19445                 :          0 :         return ret;
   19446                 :            : }
   19447                 :            : 
   19448                 :            : /**
   19449                 :            :  * Create the sub policy tag rule for all meters in hierarchy.
   19450                 :            :  *
   19451                 :            :  * @param[in] dev
   19452                 :            :  *   Pointer to Ethernet device.
   19453                 :            :  * @param[in] fm
   19454                 :            :  *   Meter information table.
   19455                 :            :  * @param[in] src_port
   19456                 :            :  *   The src port this extra rule should use.
   19457                 :            :  * @param[in] item
   19458                 :            :  *   The src port match item.
   19459                 :            :  * @param[out] error
   19460                 :            :  *   Perform verbose error reporting if not NULL.
   19461                 :            :  * @return
   19462                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19463                 :            :  */
   19464                 :            : static int
   19465                 :          0 : flow_dv_meter_hierarchy_rule_create(struct rte_eth_dev *dev,
   19466                 :            :                                 struct mlx5_flow_meter_info *fm,
   19467                 :            :                                 int32_t src_port,
   19468                 :            :                                 const struct rte_flow_item *item,
   19469                 :            :                                 struct rte_flow_error *error)
   19470                 :            : {
   19471                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19472                 :            :         struct mlx5_flow_meter_policy *mtr_policy;
   19473                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy;
   19474                 :          0 :         struct mlx5_flow_meter_info *next_fm = NULL;
   19475                 :            :         struct mlx5_flow_meter_policy *next_policy;
   19476                 :            :         struct mlx5_flow_meter_sub_policy *next_sub_policy;
   19477                 :            :         struct mlx5_flow_tbl_data_entry *tbl_data;
   19478                 :            :         struct mlx5_sub_policy_color_rule *color_rule;
   19479                 :            :         struct mlx5_meter_policy_acts acts;
   19480                 :            :         uint32_t color_reg_c_idx;
   19481                 :            :         bool mtr_first = (src_port != UINT16_MAX) ? true : false;
   19482                 :          0 :         struct rte_flow_attr attr = {
   19483                 :            :                 .group = MLX5_FLOW_TABLE_LEVEL_POLICY,
   19484                 :            :                 .priority = 0,
   19485                 :            :                 .ingress = 0,
   19486                 :            :                 .egress = 0,
   19487                 :            :                 .transfer = 1,
   19488                 :            :                 .reserved = 0,
   19489                 :            :         };
   19490                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_TRANSFER;
   19491                 :            :         struct {
   19492                 :            :                 struct mlx5_flow_meter_policy *fm_policy;
   19493                 :            :                 struct mlx5_flow_meter_info *next_fm;
   19494                 :            :                 struct mlx5_sub_policy_color_rule *tag_rule[RTE_COLORS];
   19495                 :          0 :         } fm_info[MLX5_MTR_CHAIN_MAX_NUM] = { {0} };
   19496                 :            :         uint32_t fm_cnt = 0;
   19497                 :            :         uint32_t i, j;
   19498                 :            : 
   19499                 :          0 :         color_reg_c_idx = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, error);
   19500                 :            :         /* Get all fms who need to create the tag color rule. */
   19501                 :            :         do {
   19502                 :          0 :                 bool skip = false;
   19503                 :            : 
   19504                 :          0 :                 mtr_policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
   19505                 :            :                 MLX5_ASSERT(mtr_policy);
   19506         [ #  # ]:          0 :                 if (mlx5_meter_hierarchy_skip_tag_rule(priv, mtr_policy, src_port,
   19507                 :            :                                                        &next_fm, &skip, error))
   19508                 :          0 :                         goto err_exit;
   19509         [ #  # ]:          0 :                 if (!skip) {
   19510                 :          0 :                         fm_info[fm_cnt].fm_policy = mtr_policy;
   19511                 :          0 :                         fm_info[fm_cnt].next_fm = next_fm;
   19512         [ #  # ]:          0 :                         if (++fm_cnt >= MLX5_MTR_CHAIN_MAX_NUM) {
   19513                 :          0 :                                 rte_flow_error_set(error, errno,
   19514                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19515                 :            :                                         "Exceed max meter number in hierarchy.");
   19516                 :          0 :                                 goto err_exit;
   19517                 :            :                         }
   19518                 :            :                 }
   19519                 :          0 :                 fm = next_fm;
   19520         [ #  # ]:          0 :         } while (fm);
   19521                 :            :         /* Create tag color rules for all needed fms. */
   19522         [ #  # ]:          0 :         for (i = 0; i < fm_cnt; i++) {
   19523                 :            :                 void *mtr_action;
   19524                 :            : 
   19525                 :          0 :                 mtr_policy = fm_info[i].fm_policy;
   19526                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19527                 :          0 :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19528         [ #  # ]:          0 :                 for (j = 0; j < RTE_COLORS; j++) {
   19529                 :            :                         uint8_t act_n = 0;
   19530                 :            :                         struct mlx5_flow_dv_modify_hdr_resource *modify_hdr = NULL;
   19531                 :            :                         struct mlx5_flow_dv_port_id_action_resource *port_action;
   19532                 :            :                         uint8_t fate_action;
   19533                 :            : 
   19534         [ #  # ]:          0 :                         if (j == RTE_COLOR_RED) {
   19535                 :            :                                 fate_action = MLX5_FLOW_FATE_DROP;
   19536                 :            :                         } else {
   19537                 :          0 :                                 fate_action = mtr_policy->act_cnt[j].fate_action;
   19538                 :          0 :                                 modify_hdr = mtr_policy->act_cnt[j].modify_hdr;
   19539                 :          0 :                                 if (fate_action != MLX5_FLOW_FATE_MTR &&
   19540   [ #  #  #  # ]:          0 :                                     fate_action != MLX5_FLOW_FATE_PORT_ID &&
   19541                 :            :                                     fate_action != MLX5_FLOW_FATE_DROP)
   19542                 :          0 :                                         continue;
   19543                 :            :                         }
   19544                 :          0 :                         color_rule = mlx5_malloc(MLX5_MEM_ZERO,
   19545                 :            :                                                  sizeof(struct mlx5_sub_policy_color_rule),
   19546                 :            :                                                  0, SOCKET_ID_ANY);
   19547         [ #  # ]:          0 :                         if (!color_rule) {
   19548                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19549                 :          0 :                                 rte_flow_error_set(error, ENOMEM,
   19550                 :            :                                                    RTE_FLOW_ERROR_TYPE_ACTION, NULL,
   19551                 :            :                                                    "No memory to create tag color rule.");
   19552                 :          0 :                                 goto err_exit;
   19553                 :            :                         }
   19554                 :          0 :                         color_rule->src_port = src_port;
   19555                 :            :                         /* Prepare to create color rule. */
   19556         [ #  # ]:          0 :                         if (fate_action == MLX5_FLOW_FATE_MTR) {
   19557                 :          0 :                                 next_fm = fm_info[i].next_fm;
   19558         [ #  # ]:          0 :                                 if (mlx5_flow_meter_attach(priv, next_fm, &attr, error)) {
   19559                 :          0 :                                         mlx5_free(color_rule);
   19560                 :            :                                         rte_spinlock_unlock(&mtr_policy->sl);
   19561                 :          0 :                                         goto err_exit;
   19562                 :            :                                 }
   19563         [ #  # ]:          0 :                                 mtr_action = (next_fm->color_aware && j == RTE_COLOR_YELLOW) ?
   19564         [ #  # ]:          0 :                                                                         next_fm->meter_action_y :
   19565                 :            :                                                                         next_fm->meter_action_g;
   19566                 :          0 :                                 next_policy = mlx5_flow_meter_policy_find(dev, next_fm->policy_id,
   19567                 :            :                                                                           NULL);
   19568                 :            :                                 MLX5_ASSERT(next_policy);
   19569                 :          0 :                                 next_sub_policy = next_policy->sub_policys[domain][0];
   19570                 :          0 :                                 tbl_data = container_of(next_sub_policy->tbl_rsc,
   19571                 :            :                                                         struct mlx5_flow_tbl_data_entry, tbl);
   19572         [ #  # ]:          0 :                                 if (mtr_first) {
   19573                 :          0 :                                         acts.dv_actions[act_n++] = mtr_action;
   19574         [ #  # ]:          0 :                                         if (modify_hdr)
   19575                 :          0 :                                                 acts.dv_actions[act_n++] = modify_hdr->action;
   19576                 :            :                                 } else {
   19577         [ #  # ]:          0 :                                         if (modify_hdr)
   19578                 :          0 :                                                 acts.dv_actions[act_n++] = modify_hdr->action;
   19579                 :          0 :                                         acts.dv_actions[act_n++] = mtr_action;
   19580                 :            :                                 }
   19581                 :          0 :                                 acts.dv_actions[act_n++] = tbl_data->jump.action;
   19582                 :          0 :                                 acts.actions_n = act_n;
   19583         [ #  # ]:          0 :                         } else if (fate_action == MLX5_FLOW_FATE_PORT_ID) {
   19584                 :            :                                 port_action =
   19585                 :          0 :                                         mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID],
   19586                 :            :                                                        mtr_policy->act_cnt[j].rix_port_id_action);
   19587         [ #  # ]:          0 :                                 if (!port_action) {
   19588                 :          0 :                                         mlx5_free(color_rule);
   19589                 :            :                                         rte_spinlock_unlock(&mtr_policy->sl);
   19590                 :          0 :                                         goto err_exit;
   19591                 :            :                                 }
   19592         [ #  # ]:          0 :                                 if (modify_hdr)
   19593                 :          0 :                                         acts.dv_actions[act_n++] = modify_hdr->action;
   19594                 :          0 :                                 acts.dv_actions[act_n++] = port_action->action;
   19595                 :          0 :                                 acts.actions_n = act_n;
   19596                 :            :                         } else {
   19597                 :          0 :                                 acts.dv_actions[act_n++] = mtr_policy->dr_drop_action[domain];
   19598                 :          0 :                                 acts.actions_n = act_n;
   19599                 :            :                         }
   19600                 :          0 :                         fm_info[i].tag_rule[j] = color_rule;
   19601                 :          0 :                         TAILQ_INSERT_TAIL(&sub_policy->color_rules[j], color_rule, next_port);
   19602         [ #  # ]:          0 :                         if (__flow_dv_create_policy_matcher(dev, color_reg_c_idx,
   19603                 :            :                                                 MLX5_MTR_POLICY_MATCHER_PRIO, sub_policy,
   19604                 :            :                                                 &attr, true, item, &color_rule->matcher, error)) {
   19605                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19606                 :          0 :                                 rte_flow_error_set(error, errno,
   19607                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19608                 :            :                                                    "Failed to create hierarchy meter matcher.");
   19609                 :          0 :                                 goto err_exit;
   19610                 :            :                         }
   19611         [ #  # ]:          0 :                         if (__flow_dv_create_policy_flow(dev, color_reg_c_idx, (enum rte_color)j,
   19612                 :            :                                                 color_rule->matcher,
   19613                 :          0 :                                                 acts.actions_n, acts.dv_actions,
   19614                 :            :                                                 true, item, &color_rule->rule, &attr)) {
   19615                 :            :                                 rte_spinlock_unlock(&mtr_policy->sl);
   19616                 :          0 :                                 rte_flow_error_set(error, errno,
   19617                 :            :                                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   19618                 :            :                                                    "Failed to create hierarchy meter rule.");
   19619                 :          0 :                                 goto err_exit;
   19620                 :            :                         }
   19621                 :            :                 }
   19622                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19623                 :            :         }
   19624                 :            :         return 0;
   19625                 :          0 : err_exit:
   19626         [ #  # ]:          0 :         for (i = 0; i < fm_cnt; i++) {
   19627                 :          0 :                 mtr_policy = fm_info[i].fm_policy;
   19628                 :          0 :                 rte_spinlock_lock(&mtr_policy->sl);
   19629                 :          0 :                 sub_policy = mtr_policy->sub_policys[domain][0];
   19630         [ #  # ]:          0 :                 for (j = 0; j < RTE_COLORS; j++) {
   19631                 :          0 :                         color_rule = fm_info[i].tag_rule[j];
   19632         [ #  # ]:          0 :                         if (!color_rule)
   19633                 :          0 :                                 continue;
   19634         [ #  # ]:          0 :                         if (color_rule->rule)
   19635                 :            :                                 mlx5_flow_os_destroy_flow(color_rule->rule);
   19636         [ #  # ]:          0 :                         if (color_rule->matcher) {
   19637                 :            :                                 struct mlx5_flow_tbl_data_entry *tbl =
   19638                 :          0 :                                         container_of(color_rule->matcher->tbl, typeof(*tbl), tbl);
   19639                 :          0 :                                 mlx5_list_unregister(tbl->matchers, &color_rule->matcher->entry);
   19640                 :            :                         }
   19641         [ #  # ]:          0 :                         if (fm_info[i].next_fm)
   19642                 :          0 :                                 mlx5_flow_meter_detach(priv, fm_info[i].next_fm);
   19643         [ #  # ]:          0 :                         TAILQ_REMOVE(&sub_policy->color_rules[j], color_rule, next_port);
   19644                 :          0 :                         mlx5_free(color_rule);
   19645                 :            :                 }
   19646                 :            :                 rte_spinlock_unlock(&mtr_policy->sl);
   19647                 :            :         }
   19648                 :          0 :         return -rte_errno;
   19649                 :            : }
   19650                 :            : 
   19651                 :            : /**
   19652                 :            :  * Destroy the sub policy table with RX queue.
   19653                 :            :  *
   19654                 :            :  * @param[in] dev
   19655                 :            :  *   Pointer to Ethernet device.
   19656                 :            :  * @param[in] mtr_policy
   19657                 :            :  *   Pointer to meter policy table.
   19658                 :            :  */
   19659                 :            : static void
   19660                 :          0 : flow_dv_destroy_sub_policy_with_rxq(struct rte_eth_dev *dev,
   19661                 :            :                                     struct mlx5_flow_meter_policy *mtr_policy)
   19662                 :            : {
   19663                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19664                 :            :         struct mlx5_flow_meter_sub_policy *sub_policy = NULL;
   19665                 :            :         uint32_t domain = MLX5_MTR_DOMAIN_INGRESS;
   19666                 :            :         uint32_t i, j;
   19667                 :            :         uint16_t sub_policy_num, new_policy_num;
   19668                 :            : 
   19669                 :          0 :         rte_spinlock_lock(&mtr_policy->sl);
   19670         [ #  # ]:          0 :         for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
   19671      [ #  #  # ]:          0 :                 switch (mtr_policy->act_cnt[i].fate_action) {
   19672                 :          0 :                 case MLX5_FLOW_FATE_SHARED_RSS:
   19673                 :          0 :                         sub_policy_num = (mtr_policy->sub_policy_num >>
   19674                 :            :                         (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain)) &
   19675                 :            :                         MLX5_MTR_SUB_POLICY_NUM_MASK;
   19676                 :            :                         new_policy_num = sub_policy_num;
   19677         [ #  # ]:          0 :                         for (j = 0; j < sub_policy_num; j++) {
   19678                 :          0 :                                 sub_policy =
   19679                 :          0 :                                         mtr_policy->sub_policys[domain][j];
   19680         [ #  # ]:          0 :                                 if (sub_policy) {
   19681                 :          0 :                                         __flow_dv_destroy_sub_policy_rules(dev,
   19682                 :            :                                                 sub_policy);
   19683                 :          0 :                                 if (sub_policy !=
   19684         [ #  # ]:          0 :                                         mtr_policy->sub_policys[domain][0]) {
   19685                 :          0 :                                         mtr_policy->sub_policys[domain][j] =
   19686                 :            :                                                                 NULL;
   19687                 :          0 :                                         mlx5_ipool_free
   19688                 :          0 :                                 (priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],
   19689                 :          0 :                                                 sub_policy->idx);
   19690                 :          0 :                                                 new_policy_num--;
   19691                 :            :                                         }
   19692                 :            :                                 }
   19693                 :            :                         }
   19694         [ #  # ]:          0 :                         if (new_policy_num != sub_policy_num) {
   19695                 :          0 :                                 mtr_policy->sub_policy_num &=
   19696                 :            :                                 ~(MLX5_MTR_SUB_POLICY_NUM_MASK <<
   19697                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain));
   19698                 :          0 :                                 mtr_policy->sub_policy_num |=
   19699                 :            :                                 (new_policy_num &
   19700                 :            :                                         MLX5_MTR_SUB_POLICY_NUM_MASK) <<
   19701                 :            :                                 (MLX5_MTR_SUB_POLICY_NUM_SHIFT * domain);
   19702                 :            :                         }
   19703                 :            :                         break;
   19704                 :          0 :                 case MLX5_FLOW_FATE_QUEUE:
   19705                 :          0 :                         sub_policy = mtr_policy->sub_policys[domain][0];
   19706                 :          0 :                         __flow_dv_destroy_sub_policy_rules(dev,
   19707                 :            :                                                            sub_policy);
   19708                 :          0 :                         break;
   19709                 :            :                 default:
   19710                 :            :                         /*Other actions without queue and do nothing*/
   19711                 :            :                         break;
   19712                 :            :                 }
   19713                 :            :         }
   19714                 :            :         rte_spinlock_unlock(&mtr_policy->sl);
   19715                 :          0 : }
   19716                 :            : /**
   19717                 :            :  * Check whether the DR drop action is supported on the root table or not.
   19718                 :            :  *
   19719                 :            :  * Create a simple flow with DR drop action on root table to validate
   19720                 :            :  * if DR drop action on root table is supported or not.
   19721                 :            :  *
   19722                 :            :  * @param[in] dev
   19723                 :            :  *   Pointer to rte_eth_dev structure.
   19724                 :            :  *
   19725                 :            :  * @return
   19726                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19727                 :            :  */
   19728                 :            : int
   19729                 :          0 : mlx5_flow_discover_dr_action_support(struct rte_eth_dev *dev)
   19730                 :            : {
   19731                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19732                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   19733                 :          0 :         struct mlx5_flow_dv_match_params mask = {
   19734                 :            :                 .size = sizeof(mask.buf),
   19735                 :            :         };
   19736                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19737                 :            :                 .size = sizeof(value.buf),
   19738                 :            :         };
   19739                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   19740                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   19741                 :            :                 .priority = 0,
   19742                 :            :                 .match_criteria_enable = 0,
   19743                 :            :                 .match_mask = (void *)&mask,
   19744                 :            :         };
   19745                 :            :         struct mlx5_flow_tbl_resource *tbl = NULL;
   19746                 :            :         void *matcher = NULL;
   19747                 :            :         void *flow = NULL;
   19748                 :            :         int ret = -1;
   19749                 :            : 
   19750                 :          0 :         tbl = mlx5_flow_dv_tbl_resource_get(dev, 0, 0, 0, false, NULL,
   19751                 :            :                                             0, 0, 0, NULL);
   19752         [ #  # ]:          0 :         if (!tbl)
   19753                 :          0 :                 goto err;
   19754         [ #  # ]:          0 :         dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf);
   19755                 :            :         __flow_dv_adjust_buf_size(&mask.size, dv_attr.match_criteria_enable);
   19756                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   19757                 :            :                                                tbl->obj, &matcher);
   19758                 :            :         if (ret)
   19759                 :          0 :                 goto err;
   19760         [ #  # ]:          0 :         __flow_dv_adjust_buf_size(&value.size, dv_attr.match_criteria_enable);
   19761                 :          0 :         ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 1,
   19762                 :            :                                        &sh->dr_drop_action, &flow);
   19763                 :          0 : err:
   19764                 :            :         /*
   19765                 :            :          * If DR drop action is not supported on root table, flow create will
   19766                 :            :          * be failed with EOPNOTSUPP or EPROTONOSUPPORT.
   19767                 :            :          */
   19768         [ #  # ]:          0 :         if (!flow) {
   19769         [ #  # ]:          0 :                 if (matcher &&
   19770         [ #  # ]:          0 :                     (errno == EPROTONOSUPPORT || errno == EOPNOTSUPP))
   19771                 :          0 :                         DRV_LOG(INFO, "DR drop action is not supported in root table.");
   19772                 :            :                 else
   19773                 :          0 :                         DRV_LOG(ERR, "Unexpected error in DR drop action support detection");
   19774                 :            :                 ret = -1;
   19775                 :            :         } else {
   19776                 :            :                 claim_zero(mlx5_flow_os_destroy_flow(flow));
   19777                 :            :         }
   19778         [ #  # ]:          0 :         if (matcher)
   19779                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher));
   19780         [ #  # ]:          0 :         if (tbl)
   19781                 :          0 :                 mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   19782                 :          0 :         return ret;
   19783                 :            : }
   19784                 :            : 
   19785                 :            : /**
   19786                 :            :  * Validate the batch counter support in root table.
   19787                 :            :  *
   19788                 :            :  * Create a simple flow with invalid counter and drop action on root table to
   19789                 :            :  * validate if batch counter with offset on root table is supported or not.
   19790                 :            :  *
   19791                 :            :  * @param[in] dev
   19792                 :            :  *   Pointer to rte_eth_dev structure.
   19793                 :            :  *
   19794                 :            :  * @return
   19795                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
   19796                 :            :  */
   19797                 :            : int
   19798                 :          0 : mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev)
   19799                 :            : {
   19800                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19801                 :          0 :         struct mlx5_dev_ctx_shared *sh = priv->sh;
   19802                 :          0 :         struct mlx5_flow_dv_match_params mask = {
   19803                 :            :                 .size = sizeof(mask.buf),
   19804                 :            :         };
   19805                 :          0 :         struct mlx5_flow_dv_match_params value = {
   19806                 :            :                 .size = sizeof(value.buf),
   19807                 :            :         };
   19808                 :          0 :         struct mlx5dv_flow_matcher_attr dv_attr = {
   19809                 :            :                 .type = IBV_FLOW_ATTR_NORMAL,
   19810                 :            :                 .flags = IBV_FLOW_ATTR_FLAGS_EGRESS,
   19811                 :            :                 .priority = 0,
   19812                 :            :                 .match_criteria_enable = 0,
   19813                 :            :                 .match_mask = (void *)&mask,
   19814                 :            :         };
   19815                 :          0 :         void *actions[2] = { 0 };
   19816                 :            :         struct mlx5_flow_tbl_resource *tbl = NULL;
   19817                 :            :         struct mlx5_devx_obj *dcs = NULL;
   19818                 :            :         void *matcher = NULL;
   19819                 :            :         void *flow = NULL;
   19820                 :            :         int ret = -1;
   19821                 :            : 
   19822                 :          0 :         tbl = mlx5_flow_dv_tbl_resource_get(dev, 0, 1, 0, false, NULL,
   19823                 :            :                                             0, 0, 0, NULL);
   19824         [ #  # ]:          0 :         if (!tbl)
   19825                 :          0 :                 goto err;
   19826                 :          0 :         dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->cdev->ctx, 0x4);
   19827         [ #  # ]:          0 :         if (!dcs)
   19828                 :          0 :                 goto err;
   19829                 :          0 :         ret = mlx5_flow_os_create_flow_action_count(dcs->obj, UINT16_MAX,
   19830                 :            :                                                     &actions[0]);
   19831                 :            :         if (ret)
   19832                 :          0 :                 goto err;
   19833         [ #  # ]:          0 :         dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf);
   19834                 :            :         __flow_dv_adjust_buf_size(&mask.size, dv_attr.match_criteria_enable);
   19835                 :          0 :         ret = mlx5_flow_os_create_flow_matcher(sh->cdev->ctx, &dv_attr,
   19836                 :            :                                                tbl->obj, &matcher);
   19837                 :            :         if (ret)
   19838                 :          0 :                 goto err;
   19839         [ #  # ]:          0 :         __flow_dv_adjust_buf_size(&value.size, dv_attr.match_criteria_enable);
   19840                 :            :         ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 1,
   19841                 :            :                                        actions, &flow);
   19842                 :          0 : err:
   19843                 :            :         /*
   19844                 :            :          * If batch counter with offset is not supported, the driver will not
   19845                 :            :          * validate the invalid offset value, flow create should success.
   19846                 :            :          * In this case, it means batch counter is not supported in root table.
   19847                 :            :          *
   19848                 :            :          * Otherwise, if flow create is failed, counter offset is supported.
   19849                 :            :          */
   19850         [ #  # ]:          0 :         if (flow) {
   19851                 :          0 :                 DRV_LOG(INFO, "Batch counter is not supported in root "
   19852                 :            :                               "table. Switch to fallback mode.");
   19853                 :          0 :                 rte_errno = ENOTSUP;
   19854                 :            :                 ret = -rte_errno;
   19855                 :            :                 claim_zero(mlx5_flow_os_destroy_flow(flow));
   19856                 :            :         } else {
   19857                 :            :                 /* Check matcher to make sure validate fail at flow create. */
   19858   [ #  #  #  # ]:          0 :                 if (!matcher || (matcher && errno != EINVAL))
   19859                 :          0 :                         DRV_LOG(ERR, "Unexpected error in counter offset "
   19860                 :            :                                      "support detection");
   19861                 :            :                 ret = 0;
   19862                 :            :         }
   19863         [ #  # ]:          0 :         if (actions[0])
   19864                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_action(actions[0]));
   19865         [ #  # ]:          0 :         if (matcher)
   19866                 :            :                 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher));
   19867         [ #  # ]:          0 :         if (tbl)
   19868                 :          0 :                 mlx5_flow_dv_tbl_resource_release(MLX5_SH(dev), tbl);
   19869         [ #  # ]:          0 :         if (dcs)
   19870                 :          0 :                 claim_zero(mlx5_devx_cmd_destroy(dcs));
   19871                 :          0 :         return ret;
   19872                 :            : }
   19873                 :            : 
   19874                 :            : /**
   19875                 :            :  * Query a devx counter.
   19876                 :            :  *
   19877                 :            :  * @param[in] dev
   19878                 :            :  *   Pointer to the Ethernet device structure.
   19879                 :            :  * @param[in] cnt
   19880                 :            :  *   Index to the flow counter.
   19881                 :            :  * @param[in] clear
   19882                 :            :  *   Set to clear the counter statistics.
   19883                 :            :  * @param[out] pkts
   19884                 :            :  *   The statistics value of packets.
   19885                 :            :  * @param[out] bytes
   19886                 :            :  *   The statistics value of bytes.
   19887                 :            :  *
   19888                 :            :  * @return
   19889                 :            :  *   0 on success, otherwise return -1.
   19890                 :            :  */
   19891                 :            : static int
   19892                 :          0 : flow_dv_counter_query(struct rte_eth_dev *dev, uint32_t counter, bool clear,
   19893                 :            :                       uint64_t *pkts, uint64_t *bytes, void **action)
   19894                 :            : {
   19895                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19896                 :            :         struct mlx5_flow_counter *cnt;
   19897                 :            :         uint64_t inn_pkts, inn_bytes;
   19898                 :            :         int ret;
   19899                 :            : 
   19900         [ #  # ]:          0 :         if (!priv->sh->cdev->config.devx)
   19901                 :            :                 return -1;
   19902                 :            : 
   19903                 :          0 :         ret = _flow_dv_query_count(dev, counter, &inn_pkts, &inn_bytes);
   19904         [ #  # ]:          0 :         if (ret)
   19905                 :            :                 return -1;
   19906                 :            :         cnt = flow_dv_counter_get_by_idx(dev, counter, NULL);
   19907         [ #  # ]:          0 :         if (cnt && action)
   19908                 :          0 :                 *action = cnt->action;
   19909                 :            : 
   19910                 :          0 :         *pkts = inn_pkts - cnt->hits;
   19911                 :          0 :         *bytes = inn_bytes - cnt->bytes;
   19912         [ #  # ]:          0 :         if (clear) {
   19913                 :          0 :                 cnt->hits = inn_pkts;
   19914                 :          0 :                 cnt->bytes = inn_bytes;
   19915                 :            :         }
   19916                 :            :         return 0;
   19917                 :            : }
   19918                 :            : 
   19919                 :            : /**
   19920                 :            :  * Get aged-out flows.
   19921                 :            :  *
   19922                 :            :  * @param[in] dev
   19923                 :            :  *   Pointer to the Ethernet device structure.
   19924                 :            :  * @param[in] context
   19925                 :            :  *   The address of an array of pointers to the aged-out flows contexts.
   19926                 :            :  * @param[in] nb_contexts
   19927                 :            :  *   The length of context array pointers.
   19928                 :            :  * @param[out] error
   19929                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   19930                 :            :  *   error only.
   19931                 :            :  *
   19932                 :            :  * @return
   19933                 :            :  *   how many contexts get in success, otherwise negative errno value.
   19934                 :            :  *   if nb_contexts is 0, return the amount of all aged contexts.
   19935                 :            :  *   if nb_contexts is not 0 , return the amount of aged flows reported
   19936                 :            :  *   in the context array.
   19937                 :            :  * @note: only stub for now
   19938                 :            :  */
   19939                 :            : static int
   19940                 :          0 : flow_dv_get_aged_flows(struct rte_eth_dev *dev,
   19941                 :            :                     void **context,
   19942                 :            :                     uint32_t nb_contexts,
   19943                 :            :                     struct rte_flow_error *error)
   19944                 :            : {
   19945                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   19946                 :            :         struct mlx5_age_info *age_info;
   19947                 :            :         struct mlx5_age_param *age_param;
   19948                 :            :         struct mlx5_flow_counter *counter;
   19949                 :            :         struct mlx5_aso_age_action *act;
   19950                 :            :         int nb_flows = 0;
   19951                 :            : 
   19952         [ #  # ]:          0 :         if (nb_contexts && !context)
   19953                 :          0 :                 return rte_flow_error_set(error, EINVAL,
   19954                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   19955                 :            :                                           NULL, "empty context");
   19956                 :          0 :         age_info = GET_PORT_AGE_INFO(priv);
   19957                 :          0 :         rte_spinlock_lock(&age_info->aged_sl);
   19958         [ #  # ]:          0 :         LIST_FOREACH(act, &age_info->aged_aso, next) {
   19959                 :          0 :                 nb_flows++;
   19960         [ #  # ]:          0 :                 if (nb_contexts) {
   19961                 :          0 :                         context[nb_flows - 1] = act->age_params.context;
   19962         [ #  # ]:          0 :                         if (!(--nb_contexts))
   19963                 :            :                                 break;
   19964                 :            :                 }
   19965                 :            :         }
   19966         [ #  # ]:          0 :         TAILQ_FOREACH(counter, &age_info->aged_counters, next) {
   19967                 :          0 :                 nb_flows++;
   19968         [ #  # ]:          0 :                 if (nb_contexts) {
   19969                 :            :                         age_param = MLX5_CNT_TO_AGE(counter);
   19970                 :          0 :                         context[nb_flows - 1] = age_param->context;
   19971         [ #  # ]:          0 :                         if (!(--nb_contexts))
   19972                 :            :                                 break;
   19973                 :            :                 }
   19974                 :            :         }
   19975                 :            :         rte_spinlock_unlock(&age_info->aged_sl);
   19976                 :          0 :         MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER);
   19977                 :          0 :         return nb_flows;
   19978                 :            : }
   19979                 :            : 
   19980                 :            : /*
   19981                 :            :  * Mutex-protected thunk to lock-free flow_dv_counter_alloc().
   19982                 :            :  */
   19983                 :            : static uint32_t
   19984                 :          0 : flow_dv_counter_allocate(struct rte_eth_dev *dev)
   19985                 :            : {
   19986                 :          0 :         return flow_dv_counter_alloc(dev, 0);
   19987                 :            : }
   19988                 :            : 
   19989                 :            : /**
   19990                 :            :  * Validate indirect action.
   19991                 :            :  * Dispatcher for action type specific validation.
   19992                 :            :  *
   19993                 :            :  * @param[in] dev
   19994                 :            :  *   Pointer to the Ethernet device structure.
   19995                 :            :  * @param[in] conf
   19996                 :            :  *   Indirect action configuration.
   19997                 :            :  * @param[in] action
   19998                 :            :  *   The indirect action object to validate.
   19999                 :            :  * @param[out] error
   20000                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   20001                 :            :  *   error only.
   20002                 :            :  *
   20003                 :            :  * @return
   20004                 :            :  *   0 on success, otherwise negative errno value.
   20005                 :            :  */
   20006                 :            : int
   20007                 :          0 : mlx5_flow_dv_action_validate(struct rte_eth_dev *dev,
   20008                 :            :                              const struct rte_flow_indir_action_conf *conf,
   20009                 :            :                              const struct rte_flow_action *action,
   20010                 :            :                              struct rte_flow_error *err)
   20011                 :            : {
   20012                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20013                 :            :         /* called from RTE API */
   20014                 :            : 
   20015                 :            :         RTE_SET_USED(conf);
   20016   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
   20017                 :          0 :         case RTE_FLOW_ACTION_TYPE_RSS:
   20018                 :            :                 /*
   20019                 :            :                  * priv->obj_ops is set according to driver capabilities.
   20020                 :            :                  * When DevX capabilities are
   20021                 :            :                  * sufficient, it is set to mlx5_devx_obj_ops.
   20022                 :            :                  * Otherwise, it is set to mlx5_ibv_obj_ops.
   20023                 :            :                  * mlx5_ibv_obj_ops doesn't support ind_table_modify operation.
   20024                 :            :                  * In this case the indirect RSS action can't be used.
   20025                 :            :                  */
   20026         [ #  # ]:          0 :                 if (priv->obj_ops.ind_table_modify == NULL)
   20027                 :          0 :                         return rte_flow_error_set
   20028                 :            :                                         (err, ENOTSUP,
   20029                 :            :                                          RTE_FLOW_ERROR_TYPE_ACTION,
   20030                 :            :                                          NULL,
   20031                 :            :                                          "Indirect RSS action not supported");
   20032                 :          0 :                 return mlx5_validate_action_rss(dev, action, err);
   20033                 :          0 :         case RTE_FLOW_ACTION_TYPE_AGE:
   20034         [ #  # ]:          0 :                 if (!priv->sh->aso_age_mng)
   20035                 :          0 :                         return rte_flow_error_set(err, ENOTSUP,
   20036                 :            :                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
   20037                 :            :                                                 NULL,
   20038                 :            :                                                 "Indirect age action not supported");
   20039                 :          0 :                 return flow_dv_validate_action_age(0, action, dev, err);
   20040                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
   20041                 :          0 :                 return flow_dv_validate_action_count(dev, true, 0, false, err);
   20042                 :          0 :         case RTE_FLOW_ACTION_TYPE_CONNTRACK:
   20043         [ #  # ]:          0 :                 if (!priv->sh->ct_aso_en)
   20044                 :          0 :                         return rte_flow_error_set(err, ENOTSUP,
   20045                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
   20046                 :            :                                         "ASO CT is not supported");
   20047                 :          0 :                 return mlx5_validate_action_ct(dev, action->conf, err);
   20048                 :          0 :         default:
   20049                 :          0 :                 return rte_flow_error_set(err, ENOTSUP,
   20050                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION,
   20051                 :            :                                           NULL,
   20052                 :            :                                           "action type not supported");
   20053                 :            :         }
   20054                 :            : }
   20055                 :            : 
   20056                 :            : /*
   20057                 :            :  * Check if the RSS configurations for colors of a meter policy match
   20058                 :            :  * each other, except the queues.
   20059                 :            :  *
   20060                 :            :  * @param[in] r1
   20061                 :            :  *   Pointer to the first RSS flow action.
   20062                 :            :  * @param[in] r2
   20063                 :            :  *   Pointer to the second RSS flow action.
   20064                 :            :  *
   20065                 :            :  * @return
   20066                 :            :  *   0 on match, 1 on conflict.
   20067                 :            :  */
   20068                 :            : static inline int
   20069                 :          0 : flow_dv_mtr_policy_rss_compare(const struct rte_flow_action_rss *r1,
   20070                 :            :                                const struct rte_flow_action_rss *r2)
   20071                 :            : {
   20072         [ #  # ]:          0 :         if (r1 == NULL || r2 == NULL)
   20073                 :            :                 return 0;
   20074   [ #  #  #  #  :          0 :         if (!(r1->level <= 1 && r2->level <= 1) &&
                   #  # ]
   20075         [ #  # ]:          0 :             !(r1->level > 1 && r2->level > 1))
   20076                 :            :                 return 1;
   20077         [ #  # ]:          0 :         if (r1->func != r2->func)
   20078                 :            :                 return 1;
   20079         [ #  # ]:          0 :         if (r1->types != r2->types &&
   20080         [ #  # ]:          0 :             !((r1->types == 0 || r1->types == RTE_ETH_RSS_IP) &&
   20081         [ #  # ]:          0 :               (r2->types == 0 || r2->types == RTE_ETH_RSS_IP)))
   20082                 :            :                 return 1;
   20083   [ #  #  #  # ]:          0 :         if (r1->key || r2->key) {
   20084         [ #  # ]:          0 :                 const void *key1 = r1->key ? r1->key : mlx5_rss_hash_default_key;
   20085         [ #  # ]:          0 :                 const void *key2 = r2->key ? r2->key : mlx5_rss_hash_default_key;
   20086                 :            : 
   20087         [ #  # ]:          0 :                 if (memcmp(key1, key2, MLX5_RSS_HASH_KEY_LEN))
   20088                 :          0 :                         return 1;
   20089                 :            :         }
   20090                 :            :         return 0;
   20091                 :            : }
   20092                 :            : 
   20093                 :            : /**
   20094                 :            :  * Validate the meter hierarchy chain for meter policy.
   20095                 :            :  *
   20096                 :            :  * @param[in] dev
   20097                 :            :  *   Pointer to the Ethernet device structure.
   20098                 :            :  * @param[in] meter_id
   20099                 :            :  *   Meter id.
   20100                 :            :  * @param[in] action_flags
   20101                 :            :  *   Holds the actions detected until now.
   20102                 :            :  * @param[out] is_rss
   20103                 :            :  *   Is RSS or not.
   20104                 :            :  * @param[out] hierarchy_domain
   20105                 :            :  *   The domain bitmap for hierarchy policy.
   20106                 :            :  * @param[out] error
   20107                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   20108                 :            :  *   error only.
   20109                 :            :  *
   20110                 :            :  * @return
   20111                 :            :  *   0 on success, otherwise negative errno value with error set.
   20112                 :            :  */
   20113                 :            : static int
   20114                 :          0 : flow_dv_validate_policy_mtr_hierarchy(struct rte_eth_dev *dev,
   20115                 :            :                                   uint32_t meter_id,
   20116                 :            :                                   uint64_t action_flags,
   20117                 :            :                                   bool *is_rss,
   20118                 :            :                                   uint8_t *hierarchy_domain,
   20119                 :            :                                   struct rte_mtr_error *error)
   20120                 :            : {
   20121                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20122                 :            :         struct mlx5_flow_meter_info *fm;
   20123                 :            :         struct mlx5_flow_meter_policy *policy;
   20124                 :            :         uint8_t cnt = 1;
   20125                 :            : 
   20126         [ #  # ]:          0 :         if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
   20127                 :            :                             MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   20128                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   20129                 :            :                                         RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
   20130                 :            :                                         NULL,
   20131                 :            :                                         "Multiple fate actions not supported.");
   20132                 :          0 :         *hierarchy_domain = 0;
   20133                 :          0 :         fm = mlx5_flow_meter_find(priv, meter_id, NULL);
   20134                 :            :         while (true) {
   20135         [ #  # ]:          0 :                 if (!fm)
   20136                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   20137                 :            :                                                 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   20138                 :            :                                         "Meter not found in meter hierarchy.");
   20139         [ #  # ]:          0 :                 if (fm->def_policy)
   20140                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   20141                 :            :                                         RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   20142                 :            :                         "Non termination meter not supported in hierarchy.");
   20143         [ #  # ]:          0 :                 if (!fm->shared)
   20144                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   20145                 :            :                                         RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
   20146                 :            :                                         "Only shared meter supported in hierarchy.");
   20147                 :          0 :                 policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
   20148                 :            :                 MLX5_ASSERT(policy);
   20149                 :            :                 /**
   20150                 :            :                  * Only inherit the supported domains of the first meter in
   20151                 :            :                  * hierarchy.
   20152                 :            :                  * One meter supports at least one domain.
   20153                 :            :                  */
   20154         [ #  # ]:          0 :                 if (!*hierarchy_domain) {
   20155         [ #  # ]:          0 :                         if (policy->transfer)
   20156                 :          0 :                                 *hierarchy_domain |=
   20157                 :            :                                                 MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20158         [ #  # ]:          0 :                         if (policy->ingress)
   20159                 :          0 :                                 *hierarchy_domain |=
   20160                 :            :                                                 MLX5_MTR_DOMAIN_INGRESS_BIT;
   20161         [ #  # ]:          0 :                         if (policy->egress)
   20162                 :          0 :                                 *hierarchy_domain |= MLX5_MTR_DOMAIN_EGRESS_BIT;
   20163                 :            :                 }
   20164         [ #  # ]:          0 :                 if (!policy->is_hierarchy) {
   20165                 :          0 :                         *is_rss = policy->is_rss;
   20166                 :            :                         break;
   20167                 :            :                 }
   20168                 :          0 :                 rte_spinlock_lock(&policy->sl);
   20169                 :          0 :                 fm = mlx5_flow_meter_hierarchy_next_meter(priv, policy, NULL);
   20170                 :            :                 rte_spinlock_unlock(&policy->sl);
   20171         [ #  # ]:          0 :                 if (++cnt >= MLX5_MTR_CHAIN_MAX_NUM)
   20172                 :          0 :                         return -rte_mtr_error_set(error, EINVAL,
   20173                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
   20174                 :            :                                         "Exceed max hierarchy meter number.");
   20175                 :            :         }
   20176                 :          0 :         return 0;
   20177                 :            : }
   20178                 :            : 
   20179                 :            : /**
   20180                 :            :  * Validate meter policy actions.
   20181                 :            :  * Dispatcher for action type specific validation.
   20182                 :            :  *
   20183                 :            :  * @param[in] dev
   20184                 :            :  *   Pointer to the Ethernet device structure.
   20185                 :            :  * @param[in] action
   20186                 :            :  *   The meter policy action object to validate.
   20187                 :            :  * @param[in] attr
   20188                 :            :  *   Attributes of flow to determine steering domain.
   20189                 :            :  * @param[out] error
   20190                 :            :  *   Perform verbose error reporting if not NULL. Initialized in case of
   20191                 :            :  *   error only.
   20192                 :            :  *
   20193                 :            :  * @return
   20194                 :            :  *   0 on success, otherwise negative errno value.
   20195                 :            :  */
   20196                 :            : static int
   20197                 :          0 : flow_dv_validate_mtr_policy_acts(struct rte_eth_dev *dev,
   20198                 :            :                         const struct rte_flow_action *actions[RTE_COLORS],
   20199                 :            :                         struct rte_flow_attr *attr,
   20200                 :            :                         bool *is_rss,
   20201                 :            :                         uint8_t *domain_bitmap,
   20202                 :            :                         uint8_t *policy_mode,
   20203                 :            :                         struct rte_mtr_error *error)
   20204                 :            : {
   20205                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20206                 :          0 :         struct mlx5_sh_config *dev_conf = &priv->sh->config;
   20207                 :            :         const struct rte_flow_action *act;
   20208                 :          0 :         uint64_t action_flags[RTE_COLORS] = {0};
   20209                 :            :         int actions_n;
   20210                 :            :         int i, ret;
   20211                 :            :         struct rte_flow_error flow_err;
   20212                 :          0 :         uint8_t domain_color[RTE_COLORS] = {0};
   20213                 :            :         uint8_t def_domain = MLX5_MTR_ALL_DOMAIN_BIT;
   20214                 :          0 :         uint8_t hierarchy_domain = 0;
   20215                 :            :         const struct rte_flow_action_meter *mtr;
   20216                 :            :         const struct rte_flow_action_meter *next_mtr = NULL;
   20217                 :            :         bool def_green = false;
   20218                 :            :         bool def_yellow = false;
   20219                 :          0 :         const struct rte_flow_action_rss *rss_color[RTE_COLORS] = {NULL};
   20220                 :            :         /* Called from RTE API */
   20221   [ #  #  #  #  :          0 :         bool is_root = !(attr->group || (attr->transfer && priv->fdb_def_rule));
                   #  # ]
   20222                 :            : 
   20223         [ #  # ]:          0 :         if (!dev_conf->dv_esw_en)
   20224                 :            :                 def_domain &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20225                 :          0 :         *domain_bitmap = def_domain;
   20226                 :            :         /* Red color could only support DROP action. */
   20227         [ #  # ]:          0 :         if (!actions[RTE_COLOR_RED] ||
   20228         [ #  # ]:          0 :             actions[RTE_COLOR_RED]->type != RTE_FLOW_ACTION_TYPE_DROP)
   20229                 :          0 :                 return -rte_mtr_error_set(error, ENOTSUP,
   20230                 :            :                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   20231                 :            :                                 NULL, "Red color only supports drop action.");
   20232                 :            :         /*
   20233                 :            :          * Check default policy actions:
   20234                 :            :          * Green / Yellow: no action, Red: drop action
   20235                 :            :          * Either G or Y will trigger default policy actions to be created.
   20236                 :            :          */
   20237         [ #  # ]:          0 :         if (!actions[RTE_COLOR_GREEN] ||
   20238         [ #  # ]:          0 :             actions[RTE_COLOR_GREEN]->type == RTE_FLOW_ACTION_TYPE_END)
   20239                 :            :                 def_green = true;
   20240         [ #  # ]:          0 :         if (!actions[RTE_COLOR_YELLOW] ||
   20241         [ #  # ]:          0 :             actions[RTE_COLOR_YELLOW]->type == RTE_FLOW_ACTION_TYPE_END)
   20242                 :            :                 def_yellow = true;
   20243         [ #  # ]:          0 :         if (def_green && def_yellow) {
   20244                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_DEF;
   20245                 :          0 :                 return 0;
   20246         [ #  # ]:          0 :         } else if (!def_green && def_yellow) {
   20247                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_OG;
   20248         [ #  # ]:          0 :         } else if (def_green && !def_yellow) {
   20249                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_OY;
   20250                 :            :         } else {
   20251                 :          0 :                 *policy_mode = MLX5_MTR_POLICY_MODE_ALL;
   20252                 :            :         }
   20253                 :            :         /* Set to empty string in case of NULL pointer access by user. */
   20254                 :          0 :         flow_err.message = "";
   20255         [ #  # ]:          0 :         for (i = 0; i < RTE_COLORS; i++) {
   20256                 :          0 :                 act = actions[i];
   20257                 :          0 :                 for (action_flags[i] = 0, actions_n = 0;
   20258   [ #  #  #  # ]:          0 :                      act && act->type != RTE_FLOW_ACTION_TYPE_END;
   20259                 :          0 :                      act++) {
   20260         [ #  # ]:          0 :                         if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
   20261                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20262                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20263                 :            :                                           NULL, "too many actions");
   20264   [ #  #  #  #  :          0 :                         switch (act->type) {
          #  #  #  #  #  
                      # ]
   20265                 :          0 :                         case RTE_FLOW_ACTION_TYPE_PORT_ID:
   20266                 :            :                         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
   20267         [ #  # ]:          0 :                                 if (!dev_conf->dv_esw_en)
   20268                 :          0 :                                         return -rte_mtr_error_set(error,
   20269                 :            :                                         ENOTSUP,
   20270                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20271                 :            :                                         NULL, "PORT action validate check"
   20272                 :            :                                         " fail for ESW disable");
   20273                 :          0 :                                 ret = flow_dv_validate_action_port_id(dev,
   20274                 :            :                                                 action_flags[i],
   20275                 :            :                                                 act, attr, &flow_err);
   20276         [ #  # ]:          0 :                                 if (ret)
   20277                 :          0 :                                         return -rte_mtr_error_set(error,
   20278                 :            :                                         ENOTSUP,
   20279                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20280         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20281                 :            :                                         flow_err.message :
   20282                 :            :                                         "PORT action validate check fail");
   20283                 :          0 :                                 ++actions_n;
   20284                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_PORT_ID;
   20285                 :          0 :                                 break;
   20286                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MARK:
   20287                 :          0 :                                 ret = flow_dv_validate_action_mark(dev, act,
   20288                 :            :                                                            action_flags[i],
   20289                 :            :                                                            attr, &flow_err);
   20290         [ #  # ]:          0 :                                 if (ret < 0)
   20291                 :          0 :                                         return -rte_mtr_error_set(error,
   20292                 :            :                                         ENOTSUP,
   20293                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20294         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20295                 :            :                                         flow_err.message :
   20296                 :            :                                         "Mark action validate check fail");
   20297         [ #  # ]:          0 :                                 if (dev_conf->dv_xmeta_en !=
   20298                 :            :                                         MLX5_XMETA_MODE_LEGACY)
   20299                 :          0 :                                         return -rte_mtr_error_set(error,
   20300                 :            :                                         ENOTSUP,
   20301                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20302                 :            :                                         NULL, "Extend MARK action is "
   20303                 :            :                                         "not supported. Please try use "
   20304                 :            :                                         "default policy for meter.");
   20305                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_MARK;
   20306                 :          0 :                                 ++actions_n;
   20307                 :          0 :                                 break;
   20308                 :          0 :                         case RTE_FLOW_ACTION_TYPE_SET_TAG:
   20309                 :          0 :                                 ret = flow_dv_validate_action_set_tag(dev,
   20310                 :            :                                                         act, action_flags[i],
   20311                 :            :                                                         attr, &flow_err);
   20312         [ #  # ]:          0 :                                 if (ret)
   20313                 :          0 :                                         return -rte_mtr_error_set(error,
   20314                 :            :                                         ENOTSUP,
   20315                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20316         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20317                 :            :                                         flow_err.message :
   20318                 :            :                                         "Set tag action validate check fail");
   20319                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_SET_TAG;
   20320                 :          0 :                                 ++actions_n;
   20321                 :          0 :                                 break;
   20322                 :          0 :                         case RTE_FLOW_ACTION_TYPE_DROP:
   20323                 :          0 :                                 ret = mlx5_flow_validate_action_drop
   20324                 :            :                                         (dev, false, attr, &flow_err);
   20325         [ #  # ]:          0 :                                 if (ret < 0)
   20326                 :          0 :                                         return -rte_mtr_error_set(error,
   20327                 :            :                                         ENOTSUP,
   20328                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20329         [ #  # ]:          0 :                                         NULL, flow_err.message ?
   20330                 :            :                                         flow_err.message :
   20331                 :            :                                         "Drop action validate check fail");
   20332                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_DROP;
   20333                 :          0 :                                 ++actions_n;
   20334                 :          0 :                                 break;
   20335                 :          0 :                         case RTE_FLOW_ACTION_TYPE_QUEUE:
   20336                 :            :                                 /*
   20337                 :            :                                  * Check whether extensive
   20338                 :            :                                  * metadata feature is engaged.
   20339                 :            :                                  */
   20340         [ #  # ]:          0 :                                 if (dev_conf->dv_flow_en &&
   20341         [ #  # ]:          0 :                                     (dev_conf->dv_xmeta_en !=
   20342         [ #  # ]:          0 :                                      MLX5_XMETA_MODE_LEGACY) &&
   20343                 :          0 :                                     mlx5_flow_ext_mreg_supported(dev))
   20344                 :          0 :                                         return -rte_mtr_error_set(error,
   20345                 :            :                                           ENOTSUP,
   20346                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20347                 :            :                                           NULL, "Queue action with meta "
   20348                 :            :                                           "is not supported. Please try use "
   20349                 :            :                                           "default policy for meter.");
   20350                 :          0 :                                 ret = mlx5_flow_validate_action_queue(act,
   20351                 :            :                                                         action_flags[i], dev,
   20352                 :            :                                                         attr, &flow_err);
   20353         [ #  # ]:          0 :                                 if (ret < 0)
   20354                 :          0 :                                         return -rte_mtr_error_set(error,
   20355                 :            :                                           ENOTSUP,
   20356                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20357         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20358                 :            :                                           flow_err.message :
   20359                 :            :                                           "Queue action validate check fail");
   20360                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_QUEUE;
   20361                 :          0 :                                 ++actions_n;
   20362                 :          0 :                                 break;
   20363                 :          0 :                         case RTE_FLOW_ACTION_TYPE_RSS:
   20364         [ #  # ]:          0 :                                 if (dev_conf->dv_flow_en &&
   20365         [ #  # ]:          0 :                                     (dev_conf->dv_xmeta_en !=
   20366         [ #  # ]:          0 :                                      MLX5_XMETA_MODE_LEGACY) &&
   20367                 :          0 :                                     mlx5_flow_ext_mreg_supported(dev))
   20368                 :          0 :                                         return -rte_mtr_error_set(error,
   20369                 :            :                                           ENOTSUP,
   20370                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20371                 :            :                                           NULL, "RSS action with meta "
   20372                 :            :                                           "is not supported. Please try use "
   20373                 :            :                                           "default policy for meter.");
   20374                 :          0 :                                 ret = mlx5_validate_action_rss(dev, act,
   20375                 :            :                                                                &flow_err);
   20376         [ #  # ]:          0 :                                 if (ret < 0)
   20377                 :          0 :                                         return -rte_mtr_error_set(error,
   20378                 :            :                                           ENOTSUP,
   20379                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20380         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20381                 :            :                                           flow_err.message :
   20382                 :            :                                           "RSS action validate check fail");
   20383                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_RSS;
   20384                 :          0 :                                 ++actions_n;
   20385                 :            :                                 /* Either G or Y will set the RSS. */
   20386                 :          0 :                                 rss_color[i] = act->conf;
   20387                 :          0 :                                 break;
   20388                 :          0 :                         case RTE_FLOW_ACTION_TYPE_JUMP:
   20389                 :          0 :                                 ret = flow_dv_validate_action_jump(dev,
   20390                 :            :                                         NULL, act, action_flags[i],
   20391                 :            :                                         attr, true, &flow_err);
   20392         [ #  # ]:          0 :                                 if (ret)
   20393                 :          0 :                                         return -rte_mtr_error_set(error,
   20394                 :            :                                           ENOTSUP,
   20395                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20396         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20397                 :            :                                           flow_err.message :
   20398                 :            :                                           "Jump action validate check fail");
   20399                 :          0 :                                 ++actions_n;
   20400                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_JUMP;
   20401                 :          0 :                                 break;
   20402                 :          0 :                         case RTE_FLOW_ACTION_TYPE_METER:
   20403                 :          0 :                                 mtr = act->conf;
   20404   [ #  #  #  # ]:          0 :                                 if (next_mtr && next_mtr->mtr_id != mtr->mtr_id)
   20405                 :          0 :                                         return -rte_mtr_error_set(error, ENOTSUP,
   20406                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
   20407                 :            :                                                 "Green and Yellow must use the same meter.");
   20408                 :          0 :                                 ret = flow_dv_validate_policy_mtr_hierarchy(dev,
   20409                 :          0 :                                                         mtr->mtr_id,
   20410                 :            :                                                         action_flags[i],
   20411                 :            :                                                         is_rss,
   20412                 :            :                                                         &hierarchy_domain,
   20413                 :            :                                                         error);
   20414         [ #  # ]:          0 :                                 if (ret)
   20415                 :          0 :                                         return ret;
   20416                 :          0 :                                 ++actions_n;
   20417                 :          0 :                                 action_flags[i] |=
   20418                 :            :                                 MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;
   20419                 :            :                                 next_mtr = mtr;
   20420                 :          0 :                                 break;
   20421                 :          0 :                         case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
   20422                 :          0 :                                 ret = flow_dv_validate_action_modify_field(dev,
   20423                 :            :                                         action_flags[i], act, attr, is_root, &flow_err);
   20424         [ #  # ]:          0 :                                 if (ret < 0)
   20425                 :          0 :                                         return -rte_mtr_error_set(error,
   20426                 :            :                                           ENOTSUP,
   20427                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20428         [ #  # ]:          0 :                                           NULL, flow_err.message ?
   20429                 :            :                                           flow_err.message :
   20430                 :            :                                           "Modify field action validate check fail");
   20431                 :          0 :                                 ++actions_n;
   20432                 :          0 :                                 action_flags[i] |= MLX5_FLOW_ACTION_MODIFY_FIELD;
   20433                 :          0 :                                 break;
   20434                 :            :                         default:
   20435                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20436                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20437                 :            :                                         NULL,
   20438                 :            :                                         "Doesn't support optional action");
   20439                 :            :                         }
   20440                 :            :                 }
   20441         [ #  # ]:          0 :                 if (action_flags[i] & MLX5_FLOW_ACTION_PORT_ID) {
   20442                 :          0 :                         domain_color[i] = MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20443         [ #  # ]:          0 :                 } else if ((action_flags[i] &
   20444                 :          0 :                           (MLX5_FLOW_ACTION_RSS | MLX5_FLOW_ACTION_QUEUE)) ||
   20445         [ #  # ]:          0 :                           (action_flags[i] & MLX5_FLOW_ACTION_MARK)) {
   20446                 :            :                         /*
   20447                 :            :                          * Only support MLX5_XMETA_MODE_LEGACY
   20448                 :            :                          * so MARK action is only in ingress domain.
   20449                 :            :                          */
   20450                 :          0 :                         domain_color[i] = MLX5_MTR_DOMAIN_INGRESS_BIT;
   20451                 :            :                 } else {
   20452                 :          0 :                         domain_color[i] = def_domain;
   20453         [ #  # ]:          0 :                         if (action_flags[i] &&
   20454         [ #  # ]:          0 :                             !(action_flags[i] & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   20455                 :          0 :                                 domain_color[i] &=
   20456                 :            :                                 ~MLX5_MTR_DOMAIN_TRANSFER_BIT;
   20457                 :            :                 }
   20458         [ #  # ]:          0 :                 if (action_flags[i] &
   20459                 :            :                     MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
   20460                 :          0 :                         domain_color[i] &= hierarchy_domain;
   20461                 :            :                 /*
   20462                 :            :                  * Non-termination actions only support NIC Tx domain.
   20463                 :            :                  * The adjustion should be skipped when there is no
   20464                 :            :                  * action or only END is provided. The default domains
   20465                 :            :                  * bit-mask is set to find the MIN intersection.
   20466                 :            :                  * The action flags checking should also be skipped.
   20467                 :            :                  */
   20468         [ #  # ]:          0 :                 if ((def_green && i == RTE_COLOR_GREEN) ||
   20469         [ #  # ]:          0 :                     (def_yellow && i == RTE_COLOR_YELLOW))
   20470                 :          0 :                         continue;
   20471                 :            :                 /*
   20472                 :            :                  * Validate the drop action mutual exclusion
   20473                 :            :                  * with other actions. Drop action is mutually-exclusive
   20474                 :            :                  * with any other action, except for Count action.
   20475                 :            :                  */
   20476         [ #  # ]:          0 :                 if ((action_flags[i] & MLX5_FLOW_ACTION_DROP) &&
   20477         [ #  # ]:          0 :                     (action_flags[i] & ~MLX5_FLOW_ACTION_DROP)) {
   20478                 :          0 :                         return -rte_mtr_error_set(error, ENOTSUP,
   20479                 :            :                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   20480                 :            :                                 NULL, "Drop action is mutually-exclusive "
   20481                 :            :                                 "with any other action");
   20482                 :            :                 }
   20483                 :            :                 /* Eswitch has few restrictions on using items and actions */
   20484         [ #  # ]:          0 :                 if (domain_color[i] & MLX5_MTR_DOMAIN_TRANSFER_BIT) {
   20485         [ #  # ]:          0 :                         if (!mlx5_flow_ext_mreg_supported(dev) &&
   20486         [ #  # ]:          0 :                             action_flags[i] & MLX5_FLOW_ACTION_MARK)
   20487                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20488                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20489                 :            :                                         NULL, "unsupported action MARK");
   20490         [ #  # ]:          0 :                         if (action_flags[i] & MLX5_FLOW_ACTION_QUEUE)
   20491                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20492                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20493                 :            :                                         NULL, "unsupported action QUEUE");
   20494         [ #  # ]:          0 :                         if (action_flags[i] & MLX5_FLOW_ACTION_RSS)
   20495                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20496                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20497                 :            :                                         NULL, "unsupported action RSS");
   20498         [ #  # ]:          0 :                         if (!(action_flags[i] & MLX5_FLOW_FATE_ESWITCH_ACTIONS))
   20499                 :          0 :                                 return -rte_mtr_error_set(error, ENOTSUP,
   20500                 :            :                                         RTE_MTR_ERROR_TYPE_METER_POLICY,
   20501                 :            :                                         NULL, "no fate action is found");
   20502                 :            :                 } else {
   20503   [ #  #  #  # ]:          0 :                         if (!(action_flags[i] & MLX5_FLOW_FATE_ACTIONS) &&
   20504                 :            :                             (domain_color[i] & MLX5_MTR_DOMAIN_INGRESS_BIT)) {
   20505         [ #  # ]:          0 :                                 if ((domain_color[i] &
   20506                 :            :                                      MLX5_MTR_DOMAIN_EGRESS_BIT))
   20507                 :          0 :                                         domain_color[i] =
   20508                 :            :                                                 MLX5_MTR_DOMAIN_EGRESS_BIT;
   20509                 :            :                                 else
   20510                 :          0 :                                         return -rte_mtr_error_set(error,
   20511                 :            :                                                 ENOTSUP,
   20512                 :            :                                                 RTE_MTR_ERROR_TYPE_METER_POLICY,
   20513                 :            :                                                 NULL,
   20514                 :            :                                                 "no fate action is found");
   20515                 :            :                         }
   20516                 :            :                 }
   20517                 :            :         }
   20518   [ #  #  #  # ]:          0 :         if (next_mtr && *policy_mode == MLX5_MTR_POLICY_MODE_ALL) {
   20519                 :            :                 uint64_t hierarchy_type_flag =
   20520                 :            :                         MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY | MLX5_FLOW_ACTION_JUMP;
   20521         [ #  # ]:          0 :                 if (!(action_flags[RTE_COLOR_GREEN] & hierarchy_type_flag) ||
   20522         [ #  # ]:          0 :                     !(action_flags[RTE_COLOR_YELLOW] & hierarchy_type_flag))
   20523                 :          0 :                         return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_POLICY,
   20524                 :            :                                                   NULL,
   20525                 :            :                                                   "Unsupported action in meter hierarchy.");
   20526                 :            :         }
   20527                 :            :         /* If both colors have RSS, the attributes should be the same. */
   20528         [ #  # ]:          0 :         if (flow_dv_mtr_policy_rss_compare(rss_color[RTE_COLOR_GREEN],
   20529                 :            :                                            rss_color[RTE_COLOR_YELLOW]))
   20530                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   20531                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20532                 :            :                                           NULL, "policy RSS attr conflict");
   20533   [ #  #  #  # ]:          0 :         if (rss_color[RTE_COLOR_GREEN] || rss_color[RTE_COLOR_YELLOW])
   20534                 :          0 :                 *is_rss = true;
   20535                 :            :         /* "domain_color[C]" is non-zero for each color, default is ALL. */
   20536         [ #  # ]:          0 :         if (!def_green && !def_yellow &&
   20537         [ #  # ]:          0 :             domain_color[RTE_COLOR_GREEN] != domain_color[RTE_COLOR_YELLOW] &&
   20538         [ #  # ]:          0 :             !(action_flags[RTE_COLOR_GREEN] & MLX5_FLOW_ACTION_DROP) &&
   20539         [ #  # ]:          0 :             !(action_flags[RTE_COLOR_YELLOW] & MLX5_FLOW_ACTION_DROP))
   20540                 :          0 :                 return -rte_mtr_error_set(error, EINVAL,
   20541                 :            :                                           RTE_MTR_ERROR_TYPE_METER_POLICY,
   20542                 :            :                                           NULL, "policy domains conflict");
   20543                 :            :         /*
   20544                 :            :          * At least one color policy is listed in the actions, the domains
   20545                 :            :          * to be supported should be the intersection.
   20546                 :            :          */
   20547                 :          0 :         *domain_bitmap = domain_color[RTE_COLOR_GREEN] &
   20548                 :          0 :                          domain_color[RTE_COLOR_YELLOW];
   20549                 :          0 :         return 0;
   20550                 :            : }
   20551                 :            : 
   20552                 :            : static int
   20553                 :          0 : flow_dv_sync_domain(struct rte_eth_dev *dev, uint32_t domains, uint32_t flags)
   20554                 :            : {
   20555                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20556                 :            :         int ret = 0;
   20557                 :            : 
   20558   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_NIC_RX) && priv->sh->rx_domain != NULL) {
   20559                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->rx_domain,
   20560                 :            :                                                 flags);
   20561         [ #  # ]:          0 :                 if (ret != 0)
   20562                 :            :                         return ret;
   20563                 :            :         }
   20564   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_NIC_TX) && priv->sh->tx_domain != NULL) {
   20565                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->tx_domain, flags);
   20566         [ #  # ]:          0 :                 if (ret != 0)
   20567                 :            :                         return ret;
   20568                 :            :         }
   20569   [ #  #  #  # ]:          0 :         if ((domains & RTE_PMD_MLX5_DOMAIN_BIT_FDB) && priv->sh->fdb_domain != NULL) {
   20570                 :            :                 ret = mlx5_os_flow_dr_sync_domain(priv->sh->fdb_domain, flags);
   20571         [ #  # ]:          0 :                 if (ret != 0)
   20572                 :          0 :                         return ret;
   20573                 :            :         }
   20574                 :            :         return 0;
   20575                 :            : }
   20576                 :            : 
   20577                 :            : /**
   20578                 :            :  * Discover the number of available flow priorities
   20579                 :            :  * by trying to create a flow with the highest priority value
   20580                 :            :  * for each possible number.
   20581                 :            :  *
   20582                 :            :  * @param[in] dev
   20583                 :            :  *   Ethernet device.
   20584                 :            :  * @param[in] vprio
   20585                 :            :  *   List of possible number of available priorities.
   20586                 :            :  * @param[in] vprio_n
   20587                 :            :  *   Size of @p vprio array.
   20588                 :            :  * @return
   20589                 :            :  *   On success, number of available flow priorities.
   20590                 :            :  *   On failure, a negative errno-style code and rte_errno is set.
   20591                 :            :  */
   20592                 :            : static int
   20593                 :          0 : flow_dv_discover_priorities(struct rte_eth_dev *dev,
   20594                 :            :                             const uint16_t *vprio, int vprio_n)
   20595                 :            : {
   20596                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
   20597                 :          0 :         struct mlx5_indexed_pool *pool = priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW];
   20598                 :            :         struct rte_flow_item_eth eth;
   20599                 :          0 :         struct rte_flow_item item = {
   20600                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
   20601                 :            :                 .spec = &eth,
   20602                 :            :                 .mask = &eth,
   20603                 :            :         };
   20604                 :          0 :         struct mlx5_flow_dv_matcher matcher = {
   20605                 :            :                 .mask = {
   20606                 :            :                         .size = sizeof(matcher.mask.buf),
   20607                 :            :                 },
   20608                 :            :         };
   20609                 :            :         union mlx5_flow_tbl_key tbl_key;
   20610                 :            :         struct mlx5_flow flow;
   20611                 :            :         void *action;
   20612                 :            :         struct rte_flow_error error;
   20613                 :            :         uint8_t misc_mask;
   20614                 :            :         int i, err, ret = -ENOTSUP;
   20615                 :            : 
   20616                 :            :         /*
   20617                 :            :          * Prepare a flow with a catch-all pattern and a drop action.
   20618                 :            :          * Use drop queue, because shared drop action may be unavailable.
   20619                 :            :          */
   20620                 :          0 :         action = priv->drop_queue.hrxq->action;
   20621         [ #  # ]:          0 :         if (action == NULL) {
   20622                 :          0 :                 DRV_LOG(ERR, "Priority discovery requires a drop action");
   20623                 :          0 :                 rte_errno = ENOTSUP;
   20624                 :          0 :                 return -rte_errno;
   20625                 :            :         }
   20626                 :            :         memset(&flow, 0, sizeof(flow));
   20627                 :          0 :         flow.handle = mlx5_ipool_zmalloc(pool, &flow.handle_idx);
   20628         [ #  # ]:          0 :         if (flow.handle == NULL) {
   20629                 :          0 :                 DRV_LOG(ERR, "Cannot create flow handle");
   20630                 :          0 :                 rte_errno = ENOMEM;
   20631                 :          0 :                 return -rte_errno;
   20632                 :            :         }
   20633                 :          0 :         flow.ingress = true;
   20634                 :          0 :         flow.dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param);
   20635                 :          0 :         flow.dv.actions[0] = action;
   20636                 :          0 :         flow.dv.actions_n = 1;
   20637                 :            :         memset(&eth, 0, sizeof(eth));
   20638                 :          0 :         flow_dv_translate_item_eth(matcher.mask.buf, &item,
   20639                 :            :                                    /* inner */ false, /* group */ 0,
   20640                 :            :                                    MLX5_SET_MATCHER_SW_M);
   20641                 :          0 :         flow_dv_translate_item_eth(flow.dv.value.buf, &item,
   20642                 :            :                                    /* inner */ false, /* group */ 0,
   20643                 :            :                                    MLX5_SET_MATCHER_SW_V);
   20644                 :          0 :         matcher.crc = rte_raw_cksum(matcher.mask.buf, matcher.mask.size);
   20645         [ #  # ]:          0 :         for (i = 0; i < vprio_n; i++) {
   20646                 :            :                 /* Configure the next proposed maximum priority. */
   20647                 :          0 :                 matcher.priority = vprio[i] - 1;
   20648                 :            :                 memset(&tbl_key, 0, sizeof(tbl_key));
   20649                 :          0 :                 err = flow_dv_matcher_register(dev, &matcher, &tbl_key, &flow,
   20650                 :            :                                                /* tunnel */ NULL,
   20651                 :            :                                                /* group */ 0,
   20652                 :            :                                                &error);
   20653         [ #  # ]:          0 :                 if (err != 0) {
   20654                 :            :                         /* This action is pure SW and must always succeed. */
   20655                 :          0 :                         DRV_LOG(ERR, "Cannot register matcher");
   20656                 :          0 :                         ret = -rte_errno;
   20657                 :          0 :                         break;
   20658                 :            :                 }
   20659                 :            :                 /* Try to apply the flow to HW. */
   20660         [ #  # ]:          0 :                 misc_mask = flow_dv_matcher_enable(flow.handle->dvh.matcher->mask.buf);
   20661                 :            :                 __flow_dv_adjust_buf_size(&flow.dv.value.size, misc_mask);
   20662                 :          0 :                 err = mlx5_flow_os_create_flow
   20663                 :            :                                 (flow.handle->dvh.matcher->matcher_object,
   20664                 :          0 :                                  (void *)&flow.dv.value, flow.dv.actions_n,
   20665                 :            :                                  flow.dv.actions, &flow.handle->drv_flow);
   20666                 :            :                 if (err == 0) {
   20667                 :          0 :                         claim_zero(mlx5_flow_os_destroy_flow
   20668                 :            :                                                 (flow.handle->drv_flow));
   20669                 :          0 :                         flow.handle->drv_flow = NULL;
   20670                 :            :                 }
   20671                 :          0 :                 claim_zero(flow_dv_matcher_release(dev, flow.handle));
   20672         [ #  # ]:          0 :                 if (err != 0)
   20673                 :            :                         break;
   20674                 :          0 :                 ret = vprio[i];
   20675                 :            :         }
   20676                 :          0 :         mlx5_ipool_free(pool, flow.handle_idx);
   20677                 :            :         /* Set rte_errno if no expected priority value matched. */
   20678         [ #  # ]:          0 :         if (ret < 0)
   20679                 :          0 :                 rte_errno = -ret;
   20680                 :            :         return ret;
   20681                 :            : }
   20682                 :            : 
   20683                 :            : const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
   20684                 :            :         .list_create = mlx5_flow_legacy_list_create,
   20685                 :            :         .list_destroy = mlx5_flow_legacy_list_destroy,
   20686                 :            :         .validate = mlx5_flow_dv_validate,
   20687                 :            :         .prepare = flow_dv_prepare,
   20688                 :            :         .translate = flow_dv_translate,
   20689                 :            :         .apply = flow_dv_apply,
   20690                 :            :         .remove = flow_dv_remove,
   20691                 :            :         .destroy = flow_dv_destroy,
   20692                 :            :         .query = flow_dv_query,
   20693                 :            :         .create_mtr_tbls = flow_dv_create_mtr_tbls,
   20694                 :            :         .destroy_mtr_tbls = flow_dv_destroy_mtr_tbls,
   20695                 :            :         .destroy_mtr_drop_tbls = flow_dv_destroy_mtr_drop_tbls,
   20696                 :            :         .create_meter = flow_dv_mtr_alloc,
   20697                 :            :         .free_meter = flow_dv_aso_mtr_release_to_pool,
   20698                 :            :         .validate_mtr_acts = flow_dv_validate_mtr_policy_acts,
   20699                 :            :         .create_mtr_acts = flow_dv_create_mtr_policy_acts,
   20700                 :            :         .destroy_mtr_acts = flow_dv_destroy_mtr_policy_acts,
   20701                 :            :         .create_policy_rules = flow_dv_create_policy_rules,
   20702                 :            :         .destroy_policy_rules = flow_dv_destroy_policy_rules,
   20703                 :            :         .create_def_policy = flow_dv_create_def_policy,
   20704                 :            :         .destroy_def_policy = flow_dv_destroy_def_policy,
   20705                 :            :         .meter_sub_policy_rss_prepare = flow_dv_meter_sub_policy_rss_prepare,
   20706                 :            :         .meter_hierarchy_rule_create = flow_dv_meter_hierarchy_rule_create,
   20707                 :            :         .destroy_sub_policy_with_rxq = flow_dv_destroy_sub_policy_with_rxq,
   20708                 :            :         .counter_alloc = flow_dv_counter_allocate,
   20709                 :            :         .counter_free = flow_dv_counter_free,
   20710                 :            :         .counter_query = flow_dv_counter_query,
   20711                 :            :         .get_aged_flows = flow_dv_get_aged_flows,
   20712                 :            :         .action_validate = mlx5_flow_dv_action_validate,
   20713                 :            :         .action_create = mlx5_flow_dv_action_create,
   20714                 :            :         .action_destroy = mlx5_flow_dv_action_destroy,
   20715                 :            :         .action_update = mlx5_flow_dv_action_update,
   20716                 :            :         .action_query = mlx5_flow_dv_action_query,
   20717                 :            :         .sync_domain = flow_dv_sync_domain,
   20718                 :            :         .discover_priorities = flow_dv_discover_priorities,
   20719                 :            :         .item_create = mlx5_flow_dv_item_create,
   20720                 :            :         .item_release = mlx5_flow_dv_item_release,
   20721                 :            : };
   20722                 :            : 
   20723                 :            : #endif /* HAVE_IBV_FLOW_DV_SUPPORT */

Generated by: LCOV version 1.14